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.
This commit is contained in:
Wladimir J. van der Laan 2014-04-15 12:43:17 +02:00 committed by langerhans
parent 0aa5238665
commit 813a7c8d90
3 changed files with 18 additions and 0 deletions

View file

@ -479,6 +479,7 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
//TODO: this isn't identical to dogecoin reference client. //TODO: this isn't identical to dogecoin reference client.
bool IsStandardTx(const CTransaction& tx, string& reason) bool IsStandardTx(const CTransaction& tx, string& reason)
{ {
AssertLockHeld(cs_main);
if (tx.nVersion > CTransaction::CURRENT_VERSION || tx.nVersion < 1) { if (tx.nVersion > CTransaction::CURRENT_VERSION || tx.nVersion < 1) {
reason = "version"; reason = "version";
return false; return false;
@ -561,6 +562,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime) bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
{ {
AssertLockHeld(cs_main);
// Time based nLockTime implemented in 0.1.6 // Time based nLockTime implemented in 0.1.6
if (tx.nLockTime == 0) if (tx.nLockTime == 0)
return true; return true;
@ -672,6 +674,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, CCoinsViewCache& inputs)
int CMerkleTx::SetMerkleBranch(const CBlock* pblock) int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
{ {
AssertLockHeld(cs_main);
CBlock blockTmp; CBlock blockTmp;
if (pblock == NULL) { 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 AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
bool* pfMissingInputs, bool fRejectInsaneFee) bool* pfMissingInputs, bool fRejectInsaneFee)
{ {
AssertLockHeld(cs_main);
if (pfMissingInputs) if (pfMissingInputs)
*pfMissingInputs = false; *pfMissingInputs = false;
@ -954,6 +958,7 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const
{ {
if (hashBlock == 0 || nIndex == -1) if (hashBlock == 0 || nIndex == -1)
return 0; return 0;
AssertLockHeld(cs_main);
// Find the block it claims to be in // Find the block it claims to be in
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock); map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
@ -977,6 +982,7 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const
int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const
{ {
AssertLockHeld(cs_main);
int nResult = GetDepthInMainChainINTERNAL(pindexRet); int nResult = GetDepthInMainChainINTERNAL(pindexRet);
if (nResult == 0 && !mempool.exists(GetHash())) if (nResult == 0 && !mempool.exists(GetHash()))
return -1; // Not in chain, not in mempool return -1; // Not in chain, not in mempool
@ -1390,6 +1396,7 @@ int GetNumBlocksOfPeers()
bool IsInitialBlockDownload() bool IsInitialBlockDownload()
{ {
AssertLockHeld(cs_main);
if (fImporting || fReindex || chainActive.Height() < Checkpoints::GetTotalBlocksEstimate()) if (fImporting || fReindex || chainActive.Height() < Checkpoints::GetTotalBlocksEstimate())
return true; return true;
static int64_t nLastUpdate; static int64_t nLastUpdate;
@ -1409,6 +1416,7 @@ CBlockIndex *pindexBestForkTip = NULL, *pindexBestForkBase = NULL;
void CheckForkWarningConditions() void CheckForkWarningConditions()
{ {
AssertLockHeld(cs_main);
// Before we get past initial download, we cannot reliably alert about forks // 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) // (we assume we don't get stuck on a fork before the last checkpoint)
if (IsInitialBlockDownload()) if (IsInitialBlockDownload())
@ -1454,6 +1462,7 @@ void CheckForkWarningConditions()
void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
{ {
AssertLockHeld(cs_main);
// If we are on a fork that is sufficiently large, set a warning flag // If we are on a fork that is sufficiently large, set a warning flag
CBlockIndex* pfork = pindexNewForkTip; CBlockIndex* pfork = pindexNewForkTip;
CBlockIndex* plonger = chainActive.Tip(); CBlockIndex* plonger = chainActive.Tip();
@ -2183,6 +2192,7 @@ void static FindMostWorkChain() {
// Try to activate to the most-work chain (thereby connecting it). // Try to activate to the most-work chain (thereby connecting it).
bool ActivateBestChain(CValidationState &state) { bool ActivateBestChain(CValidationState &state) {
AssertLockHeld(cs_main);
CBlockIndex *pindexOldTip = chainActive.Tip(); CBlockIndex *pindexOldTip = chainActive.Tip();
bool fComplete = false; bool fComplete = false;
while (!fComplete) { while (!fComplete) {
@ -2231,6 +2241,7 @@ bool ActivateBestChain(CValidationState &state) {
bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos& pos) bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos& pos)
{ {
AssertLockHeld(cs_main);
// Check for duplicate // Check for duplicate
uint256 hash = block.GetHash(); uint256 hash = block.GetHash();
if (mapBlockIndex.count(hash)) 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) bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp)
{ {
AssertLockHeld(cs_main);
// Check for duplicate // Check for duplicate
uint256 hash = block.GetHash(); uint256 hash = block.GetHash();
if (mapBlockIndex.count(hash)) if (mapBlockIndex.count(hash))
@ -2563,6 +2575,7 @@ bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, uns
int64_t CBlockIndex::GetMedianTime() const int64_t CBlockIndex::GetMedianTime() const
{ {
AssertLockHeld(cs_main);
const CBlockIndex* pindex = this; const CBlockIndex* pindex = this;
for (int i = 0; i < nMedianTimeSpan/2; i++) 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) void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd)
{ {
AssertLockHeld(cs_main);
// Filter out duplicate requests // Filter out duplicate requests
if (pindexBegin == pnode->pindexLastGetBlocksBegin && hashEnd == pnode->hashLastGetBlocksEnd) if (pindexBegin == pnode->pindexLastGetBlocksBegin && hashEnd == pnode->hashLastGetBlocksEnd)
return; return;
@ -3091,6 +3105,7 @@ bool InitBlockIndex() {
void PrintBlockTree() void PrintBlockTree()
{ {
AssertLockHeld(cs_main);
// pre-compute tree structure // pre-compute tree structure
map<CBlockIndex*, vector<CBlockIndex*> > mapNext; map<CBlockIndex*, vector<CBlockIndex*> > mapNext;
for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)

View file

@ -20,6 +20,7 @@
QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
{ {
AssertLockHeld(cs_main);
if (!IsFinalTx(wtx, chainActive.Height() + 1)) if (!IsFinalTx(wtx, chainActive.Height() + 1))
{ {
if (wtx.nLockTime < LOCKTIME_THRESHOLD) if (wtx.nLockTime < LOCKTIME_THRESHOLD)

View file

@ -150,6 +150,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
void TransactionRecord::updateStatus(const CWalletTx &wtx) void TransactionRecord::updateStatus(const CWalletTx &wtx)
{ {
AssertLockHeld(cs_main);
// Determine transaction status // Determine transaction status
// Find the block the tx is in // Find the block the tx is in
@ -234,6 +235,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
bool TransactionRecord::statusUpdateNeeded() bool TransactionRecord::statusUpdateNeeded()
{ {
AssertLockHeld(cs_main);
return status.cur_num_blocks != chainActive.Height(); return status.cur_num_blocks != chainActive.Height();
} }