From 813a7c8d90ac754d53fb873d2708c4d2b1dcffda Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 15 Apr 2014 12:43:17 +0200 Subject: [PATCH] Add AssertLockHeld for cs_main to ChainActive-using functions All functions that use ChainActive but do not aquire the cs_main lock themselves, need to be called with the cs_main lock held. This commit adds assertions to all externally callable functions that use chainActive or chainMostWork. This will flag usages when built with -DDEBUG_LOCKORDER. --- src/main.cpp | 15 +++++++++++++++ src/qt/transactiondesc.cpp | 1 + src/qt/transactionrecord.cpp | 2 ++ 3 files changed, 18 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 072675fdf..ae37e7c27 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -479,6 +479,7 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) //TODO: this isn't identical to dogecoin reference client. bool IsStandardTx(const CTransaction& tx, string& reason) { + AssertLockHeld(cs_main); if (tx.nVersion > CTransaction::CURRENT_VERSION || tx.nVersion < 1) { reason = "version"; return false; @@ -561,6 +562,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason) bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime) { + AssertLockHeld(cs_main); // Time based nLockTime implemented in 0.1.6 if (tx.nLockTime == 0) return true; @@ -672,6 +674,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, CCoinsViewCache& inputs) int CMerkleTx::SetMerkleBranch(const CBlock* pblock) { + AssertLockHeld(cs_main); CBlock blockTmp; if (pblock == NULL) { @@ -809,6 +812,7 @@ int64_t GetMinFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree, bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, bool* pfMissingInputs, bool fRejectInsaneFee) { + AssertLockHeld(cs_main); if (pfMissingInputs) *pfMissingInputs = false; @@ -954,6 +958,7 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const { if (hashBlock == 0 || nIndex == -1) return 0; + AssertLockHeld(cs_main); // Find the block it claims to be in map::iterator mi = mapBlockIndex.find(hashBlock); @@ -977,6 +982,7 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const { + AssertLockHeld(cs_main); int nResult = GetDepthInMainChainINTERNAL(pindexRet); if (nResult == 0 && !mempool.exists(GetHash())) return -1; // Not in chain, not in mempool @@ -1390,6 +1396,7 @@ int GetNumBlocksOfPeers() bool IsInitialBlockDownload() { + AssertLockHeld(cs_main); if (fImporting || fReindex || chainActive.Height() < Checkpoints::GetTotalBlocksEstimate()) return true; static int64_t nLastUpdate; @@ -1409,6 +1416,7 @@ CBlockIndex *pindexBestForkTip = NULL, *pindexBestForkBase = NULL; void CheckForkWarningConditions() { + AssertLockHeld(cs_main); // Before we get past initial download, we cannot reliably alert about forks // (we assume we don't get stuck on a fork before the last checkpoint) if (IsInitialBlockDownload()) @@ -1454,6 +1462,7 @@ void CheckForkWarningConditions() void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) { + AssertLockHeld(cs_main); // If we are on a fork that is sufficiently large, set a warning flag CBlockIndex* pfork = pindexNewForkTip; CBlockIndex* plonger = chainActive.Tip(); @@ -2183,6 +2192,7 @@ void static FindMostWorkChain() { // Try to activate to the most-work chain (thereby connecting it). bool ActivateBestChain(CValidationState &state) { + AssertLockHeld(cs_main); CBlockIndex *pindexOldTip = chainActive.Tip(); bool fComplete = false; while (!fComplete) { @@ -2231,6 +2241,7 @@ bool ActivateBestChain(CValidationState &state) { bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos& pos) { + AssertLockHeld(cs_main); // Check for duplicate uint256 hash = block.GetHash(); if (mapBlockIndex.count(hash)) @@ -2449,6 +2460,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp) { + AssertLockHeld(cs_main); // Check for duplicate uint256 hash = block.GetHash(); if (mapBlockIndex.count(hash)) @@ -2563,6 +2575,7 @@ bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, uns int64_t CBlockIndex::GetMedianTime() const { + AssertLockHeld(cs_main); const CBlockIndex* pindex = this; for (int i = 0; i < nMedianTimeSpan/2; i++) { @@ -2575,6 +2588,7 @@ int64_t CBlockIndex::GetMedianTime() const void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd) { + AssertLockHeld(cs_main); // Filter out duplicate requests if (pindexBegin == pnode->pindexLastGetBlocksBegin && hashEnd == pnode->hashLastGetBlocksEnd) return; @@ -3091,6 +3105,7 @@ bool InitBlockIndex() { void PrintBlockTree() { + AssertLockHeld(cs_main); // pre-compute tree structure map > mapNext; for (map::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 7017bf344..8bfb99342 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -20,6 +20,7 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) { + AssertLockHeld(cs_main); if (!IsFinalTx(wtx, chainActive.Height() + 1)) { if (wtx.nLockTime < LOCKTIME_THRESHOLD) diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index c343e442e..eba650a7d 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -150,6 +150,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * void TransactionRecord::updateStatus(const CWalletTx &wtx) { + AssertLockHeld(cs_main); // Determine transaction status // Find the block the tx is in @@ -234,6 +235,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx) bool TransactionRecord::statusUpdateNeeded() { + AssertLockHeld(cs_main); return status.cur_num_blocks != chainActive.Height(); }