From c064a5bc6512596b6fba9aa570fcd40cc9d7983c Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Fri, 7 Aug 2015 07:08:37 +0300 Subject: [PATCH] WaitForLock --- src/activemasternode.cpp | 8 +++-- src/darksend.cpp | 10 ++++++- src/init.cpp | 2 ++ src/instantx.cpp | 1 + src/main.cpp | 34 ++++++++++++++++++---- src/main.h | 24 +++++++++++++++ src/masternode.cpp | 2 ++ src/miner.cpp | 4 +++ src/net.cpp | 18 ++++++++++++ src/qt/addresstablemodel.cpp | 6 ++++ src/qt/clientmodel.cpp | 9 ++---- src/qt/transactiondesc.cpp | 1 + src/qt/transactiontablemodel.cpp | 3 ++ src/qt/walletmodel.cpp | 13 +++++++++ src/rest.cpp | 1 + src/rpcblockchain.cpp | 2 ++ src/rpcmining.cpp | 3 ++ src/rpcnet.cpp | 4 +++ src/rpcserver.cpp | 3 ++ src/rpcwallet.cpp | 1 + src/spork.cpp | 2 ++ src/wallet.cpp | 50 ++++++++++++++++++++++++++++++++ src/wallet.h | 3 +- src/walletdb.cpp | 3 ++ 24 files changed, 191 insertions(+), 16 deletions(-) diff --git a/src/activemasternode.cpp b/src/activemasternode.cpp index 36b8568e17f0..03829df5a677 100644 --- a/src/activemasternode.cpp +++ b/src/activemasternode.cpp @@ -90,8 +90,11 @@ void CActiveMasternode::ManageStatus() return; } - LOCK(pwalletMain->cs_wallet); - pwalletMain->LockCoin(vin.prevout); + { + WaitForLock(pwalletMain->cs_wallet); + LOCK(pwalletMain->cs_wallet); + pwalletMain->LockCoin(vin.prevout); + } // send to all nodes CPubKey pubKeyMasternode; @@ -344,6 +347,7 @@ vector CActiveMasternode::SelectCoinsMasternode() vector filteredCoins; vector confLockedCoins; + WaitForLock(pwalletMain->cs_wallet); LOCK(pwalletMain->cs_wallet); // Temporary unlock MN coins from masternode.conf if(GetBoolArg("-mnconflock", true)) { diff --git a/src/darksend.cpp b/src/darksend.cpp index 264e74049265..07d1987c5fc8 100644 --- a/src/darksend.cpp +++ b/src/darksend.cpp @@ -260,6 +260,7 @@ void CDarksendPool::ProcessMessageDarksend(CNode* pfrom, std::string& strCommand } { + WaitForLock(cs_main); LOCK(cs_main); if(!AcceptableInputs(mempool, state, CTransaction(tx), false, NULL, false, true)) { LogPrintf("dsi -- transaction not valid! \n"); @@ -432,6 +433,7 @@ bool CDarksendPool::SetCollateralAddress(std::string strAddress){ // Unlock coins after Darksend fails or succeeds // void CDarksendPool::UnlockCoins(){ + WaitForLock(pwalletMain->cs_wallet); LOCK(pwalletMain->cs_wallet); BOOST_FOREACH(CTxIn v, lockedCoins) pwalletMain->UnlockCoin(v.prevout); @@ -565,6 +567,7 @@ void CDarksendPool::CheckFinalTransaction() CWalletTx txNew = CWalletTx(pwalletMain, finalTransaction); + WaitForLock2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet); { LogPrint("darksend", "Transaction 2: %s\n", txNew.ToString()); @@ -973,6 +976,7 @@ bool CDarksendPool::IsCollateralValid(const CTransaction& txCollateral){ LogPrint("darksend", "CDarksendPool::IsCollateralValid %s\n", txCollateral.ToString()); { + WaitForLock(cs_main); LOCK(cs_main); CValidationState state; if(!AcceptableInputs(mempool, state, txCollateral, true, NULL)){ @@ -1156,6 +1160,7 @@ void CDarksendPool::SendDarksendDenominate(std::vector& vin, std::vector< LogPrintf("Submitting tx %s\n", tx.ToString()); { + WaitForLock(cs_main); LOCK(cs_main); if(!AcceptableInputs(mempool, state, CTransaction(tx), false, NULL, false, true)){ LogPrintf("dsi -- transaction not valid! %s \n", tx.ToString()); @@ -2118,7 +2123,7 @@ bool CDarksendQueue::Sign() bool CDarksendQueue::Relay() { - + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes){ // always relay to everyone @@ -2150,6 +2155,7 @@ bool CDarksendQueue::CheckSignature() void CDarksendPool::RelayFinalTransaction(const int sessionID, const CTransaction& txNew) { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) { @@ -2179,6 +2185,7 @@ void CDarksendPool::RelayIn(const std::vector& vin, const int64_t& nAmo void CDarksendPool::RelayStatus(const int sessionID, const int newState, const int newEntriesCount, const int newAccepted, const int errorID) { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) pnode->PushMessage("dssu", sessionID, newState, newEntriesCount, newAccepted, errorID); @@ -2186,6 +2193,7 @@ void CDarksendPool::RelayStatus(const int sessionID, const int newState, const i void CDarksendPool::RelayCompletedTransaction(const int sessionID, const bool error, const int errorID) { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) pnode->PushMessage("dsc", sessionID, error, errorID); diff --git a/src/init.cpp b/src/init.cpp index d42cec89df7a..a6702dcb796e 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -186,6 +186,7 @@ void PrepareShutdown() } { + WaitForLock(cs_main); LOCK(cs_main); if (pcoinsTip != NULL) { FlushStateToDisk(); @@ -1500,6 +1501,7 @@ bool AppInit2(boost::thread_group& threadGroup) strBudgetMode = GetArg("-budgetvotemode", "auto"); if(GetBoolArg("-mnconflock", true) && pwalletMain) { + WaitForLock(pwalletMain->cs_wallet); LOCK(pwalletMain->cs_wallet); LogPrintf("Locking Masternodes:\n"); uint256 mnTxHash; diff --git a/src/instantx.cpp b/src/instantx.cpp index 1f08fd07d9e5..7293c774d51d 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -72,6 +72,7 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& bool fAccepted = false; { + WaitForLock(cs_main); LOCK(cs_main); fAccepted = AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs); } diff --git a/src/main.cpp b/src/main.cpp index e15bd9fbbe11..92a91a81bad6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -302,6 +302,7 @@ CNodeState *State(NodeId pnode) { int GetHeight() { + WaitForLock(cs_main); LOCK(cs_main); return chainActive.Height(); } @@ -317,6 +318,7 @@ void UpdatePreferredDownload(CNode* node, CNodeState* state) } void InitializeNode(NodeId nodeid, const CNode *pnode) { + WaitForLock(cs_main); LOCK(cs_main); CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second; state.name = pnode->addrName; @@ -324,6 +326,7 @@ void InitializeNode(NodeId nodeid, const CNode *pnode) { } void FinalizeNode(NodeId nodeid) { + WaitForLock(cs_main); LOCK(cs_main); CNodeState *state = State(nodeid); @@ -508,6 +511,7 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) @@ -3262,6 +3272,7 @@ bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDis bool checked = CheckBlock(*pblock, state); { + WaitForLock(cs_main); LOCK(cs_main); MarkBlockAsReceived(pblock->GetHash()); if (!checked) { @@ -3516,6 +3527,7 @@ CVerifyDB::~CVerifyDB() bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth) { + WaitForLock(cs_main); LOCK(cs_main); if (chainActive.Tip() == NULL || chainActive.Tip()->pprev == NULL) return true; @@ -3610,6 +3622,7 @@ bool LoadBlockIndex() bool InitBlockIndex() { + WaitForLock(cs_main); LOCK(cs_main); // Check whether we're already initialized if (chainActive.Genesis() != NULL) @@ -3757,6 +3770,7 @@ void static CheckBlockIndex() return; } + WaitForLock(cs_main); LOCK(cs_main); // During a reindex, we read the genesis block and call CheckBlockIndex before ActivateBestChain, @@ -4036,6 +4050,7 @@ void static ProcessGetData(CNode* pfrom) vector vNotFound; + WaitForLock(cs_main); LOCK(cs_main); while (it != pfrom->vRecvGetData.end()) { @@ -4416,6 +4431,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Mark this node as currently connected, so we update its timestamp later. if (pfrom->fNetworkNode) { + WaitForLock(cs_main); LOCK(cs_main); State(pfrom->GetId())->fCurrentlyConnected = true; } @@ -4452,6 +4468,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, { // Relay to a limited number of other nodes { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); // Use deterministic randomness to send to the same nodes for 24 hours // at a time so the setAddrKnowns of the chosen nodes prevent repeats @@ -4499,6 +4516,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, return error("message inv size() = %u", vInv.size()); } + WaitForLock(cs_main); LOCK(cs_main); std::vector vToFetch; @@ -4582,6 +4600,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, uint256 hashStop; vRecv >> locator >> hashStop; + WaitForLock(cs_main); LOCK(cs_main); // Find the last block the caller has in the main chain @@ -4618,6 +4637,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, uint256 hashStop; vRecv >> locator >> hashStop; + WaitForLock(cs_main); LOCK(cs_main); if (IsInitialBlockDownload()) @@ -4710,6 +4730,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CInv inv(MSG_TX, tx.GetHash()); pfrom->AddInventoryKnown(inv); + WaitForLock(cs_main); LOCK(cs_main); bool fMissingInputs = false; @@ -4832,6 +4853,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, ReadCompactSize(vRecv); // ignore tx count; assume it is 0. } + WaitForLock(cs_main); LOCK(cs_main); if (nCount == 0) { @@ -4876,12 +4898,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CBlock block; vRecv >> block; - TRY_LOCK(cs_main, lockMainBlock); - if(!lockMainBlock && masternodeSync.IsBlockchainSynced()) { - LogPrintf("block -- failed to lock cs_main - %s\n", block.GetHash().ToString()); - return false; - } - CInv inv(MSG_BLOCK, block.GetHash()); LogPrint("net", "received block %s peer=%d\n", inv.hash.ToString(), pfrom->id); @@ -4894,6 +4910,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->PushMessage("reject", strCommand, state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash); if (nDoS > 0) { + WaitForLock(cs_main); + LOCK(cs_main); Misbehaving(pfrom->GetId(), nDoS); } } @@ -4917,6 +4935,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, else if (strCommand == "mempool") { + WaitForLock2(cs_main, pfrom->cs_filter); LOCK2(cs_main, pfrom->cs_filter); std::vector vtxid; @@ -5032,6 +5051,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Relay pfrom->setKnown.insert(alertHash); { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) alert.RelayTo(pnode); @@ -5296,6 +5316,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) } } + WaitForLock(cs_main); TRY_LOCK(cs_main, lockMain); // Acquire cs_main for IsInitialBlockDownload() and CNodeState() if (!lockMain) return true; @@ -5304,6 +5325,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) static int64_t nLastRebroadcast; if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60)) { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) { diff --git a/src/main.h b/src/main.h index 0dfefbe97f0c..d0d1f733db70 100644 --- a/src/main.h +++ b/src/main.h @@ -27,6 +27,7 @@ #include "txmempool.h" #include "uint256.h" #include "undo.h" +#include "utiltime.h" #include #include @@ -145,6 +146,29 @@ extern CBlockIndex *pindexBestHeader; /** Minimum disk space required - used in CheckDiskSpace() */ static const uint64_t nMinDiskSpace = 52428800; +/** Wait for locks - make sure we can get locks before actually locking smth */ +void WaitForLock(CCriticalSection &cs) { + while(true){ + TRY_LOCK(cs, locked); + if(!locked) { MilliSleep(100); continue;} + break; + } +} + +void WaitForLock2(CCriticalSection &cs1, CCriticalSection &cs2) { + while(true){ + TRY_LOCK(cs1, locked1); + if(!locked1) { MilliSleep(100); continue;} + while(true){ + TRY_LOCK(cs2, locked2); + if(!locked2) { MilliSleep(100); continue;} + break; + } + break; + } +} + + /** Register a wallet to receive updates from core */ void RegisterValidationInterface(CValidationInterface* pwalletIn); /** Unregister a wallet from core */ diff --git a/src/masternode.cpp b/src/masternode.cpp index 6c581e0f7fee..2d85d560946c 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -190,6 +190,7 @@ void CMasternode::Check() tx.vout.push_back(vout); { + WaitForLock(cs_main); TRY_LOCK(cs_main, lockMain); if(!lockMain) return; @@ -420,6 +421,7 @@ bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS) tx.vout.push_back(vout); { + WaitForLock(cs_main); TRY_LOCK(cs_main, lockMain); if(!lockMain) return false; diff --git a/src/miner.cpp b/src/miner.cpp index 7c9accbd19e8..07701f601c96 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -129,6 +129,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) CAmount nFees = 0; { + WaitForLock2(cs_main, mempool.cs); LOCK2(cs_main, mempool.cs); CBlockIndex* pindexPrev = chainActive.Tip(); @@ -430,6 +431,7 @@ bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) // Found a solution { + WaitForLock(cs_main); LOCK(cs_main); if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash()) return error("DashMiner : generated block is stale"); @@ -440,6 +442,7 @@ bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) // Track how many getdata requests this block gets { + WaitForLock(wallet.cs_wallet); LOCK(wallet.cs_wallet); wallet.mapRequestCount[pblock->GetHash()] = 0; } @@ -471,6 +474,7 @@ void static BitcoinMiner(CWallet *pwallet) do { bool fvNodesEmpty; { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); fvNodesEmpty = vNodes.empty(); } diff --git a/src/net.cpp b/src/net.cpp index f578349df6c9..c9aa8ad9e268 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -355,6 +355,7 @@ CCriticalSection CNode::cs_totalBytesSent; CNode* FindNode(const CNetAddr& ip) { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) if ((CNetAddr)pnode->addr == ip) @@ -364,6 +365,7 @@ CNode* FindNode(const CNetAddr& ip) CNode* FindNode(const std::string& addrName) { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) if (pnode->addrName == addrName) @@ -373,6 +375,7 @@ CNode* FindNode(const std::string& addrName) CNode* FindNode(const CService& addr) { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes){ if(Params().NetworkID() == CBaseChainParams::REGTEST){ @@ -423,6 +426,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool darkSendMaste pnode->AddRef(); { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); vNodes.push_back(pnode); } @@ -713,6 +717,7 @@ void ThreadSocketHandler() // Disconnect nodes // { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); // Disconnect unused nodes vector vNodesCopy = vNodes; @@ -795,6 +800,7 @@ void ThreadSocketHandler() } { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) { @@ -873,6 +879,7 @@ void ThreadSocketHandler() bool whitelisted = hListenSocket.whitelisted || CNode::IsWhitelistedRange(addr); { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) if (pnode->fInbound) @@ -901,6 +908,7 @@ void ThreadSocketHandler() pnode->fWhitelisted = whitelisted; { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); vNodes.push_back(pnode); } @@ -913,6 +921,7 @@ void ThreadSocketHandler() // vector vNodesCopy; { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); vNodesCopy = vNodes; BOOST_FOREACH(CNode* pnode, vNodesCopy) @@ -1007,6 +1016,7 @@ void ThreadSocketHandler() } } { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodesCopy) pnode->Release(); @@ -1143,6 +1153,7 @@ void ThreadDNSAddressSeed() (!GetBoolArg("-forcednsseed", false))) { MilliSleep(11 * 1000); + WaitForLock(cs_vNodes); LOCK(cs_vNodes); if (vNodes.size() >= 2) { LogPrintf("P2P peers available. Skipped DNS seeding.\n"); @@ -1271,6 +1282,7 @@ void ThreadOpenConnections() int nOutbound = 0; set > setConnected; { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) { if (!pnode->fInbound) { @@ -1369,6 +1381,7 @@ void ThreadOpenAddedConnections() // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry // (keeping in mind that addnode entries can have many IPs if fNameLookup) { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) for (list >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++) @@ -1427,6 +1440,7 @@ void ThreadMessageHandler() { vector vNodesCopy; { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); vNodesCopy = vNodes; BOOST_FOREACH(CNode* pnode, vNodesCopy) { @@ -1476,6 +1490,7 @@ void ThreadMessageHandler() { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodesCopy) pnode->Release(); @@ -1771,6 +1786,7 @@ void RelayTransaction(const CTransaction& tx, const CDataStream& ss) mapRelay.insert(std::make_pair(inv, ss)); vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv)); } + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) { @@ -1791,6 +1807,7 @@ void RelayTransactionLockReq(const CTransaction& tx, bool relayToAll) CInv inv(MSG_TXLOCK_REQUEST, tx.GetHash()); //broadcast the new lock + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) { @@ -1802,6 +1819,7 @@ void RelayTransactionLockReq(const CTransaction& tx, bool relayToAll) } void RelayInv(CInv &inv, const int minProtoVersion) { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) if(pnode->nVersion >= minProtoVersion) diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index e48f6e91212b..5431af7b5fc2 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -79,6 +79,7 @@ class AddressTablePriv { cachedAddressTable.clear(); { + WaitForLock(wallet->cs_wallet); LOCK(wallet->cs_wallet); BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, wallet->mapAddressBook) { @@ -245,6 +246,7 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value, if(role == Qt::EditRole) { + WaitForLock(wallet->cs_wallet); /* For SetAddressBook / DelAddressBook */ LOCK(wallet->cs_wallet); /* For SetAddressBook / DelAddressBook */ CTxDestination curAddress = CBitcoinAddress(rec->address.toStdString()).Get(); if(index.column() == Label) @@ -357,6 +359,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con } // Check for duplicate addresses { + WaitForLock(wallet->cs_wallet); LOCK(wallet->cs_wallet); if(wallet->mapAddressBook.count(CBitcoinAddress(strAddress).Get())) { @@ -393,6 +396,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con // Add entry { + WaitForLock(wallet->cs_wallet); LOCK(wallet->cs_wallet); wallet->SetAddressBook(CBitcoinAddress(strAddress).Get(), strLabel, (type == Send ? "send" : "receive")); @@ -411,6 +415,7 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex &parent return false; } { + WaitForLock(wallet->cs_wallet); LOCK(wallet->cs_wallet); wallet->DelAddressBook(CBitcoinAddress(rec->address.toStdString()).Get()); } @@ -422,6 +427,7 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex &parent QString AddressTableModel::labelForAddress(const QString &address) const { { + WaitForLock(wallet->cs_wallet); LOCK(wallet->cs_wallet); CBitcoinAddress address_parsed(address.toStdString()); std::map::iterator mi = wallet->mapAddressBook.find(address_parsed.Get()); diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index e335f2953ce4..b4ce00207483 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -55,6 +55,7 @@ ClientModel::~ClientModel() int ClientModel::getNumConnections(unsigned int flags) const { + WaitForLock(cs_vNodes); LOCK(cs_vNodes); if (flags == CONNECTIONS_ALL) // Shortcut if we want total return vNodes.size(); @@ -76,6 +77,7 @@ QString ClientModel::getMasternodeCountString() const int ClientModel::getNumBlocks() const { + WaitForLock(cs_main); LOCK(cs_main); return chainActive.Height(); } @@ -98,6 +100,7 @@ quint64 ClientModel::getTotalBytesSent() const QDateTime ClientModel::getLastBlockDate() const { + WaitForLock(cs_main); LOCK(cs_main); if (chainActive.Tip()) return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime()); @@ -139,12 +142,6 @@ void ClientModel::updateTimer() void ClientModel::updateMnTimer() { - // Get required lock upfront. This avoids the GUI from getting stuck on - // periodical polls if the core is holding the locks for a longer time - - // for example, during a wallet rescan. - TRY_LOCK(cs_main, lockMain); - if(!lockMain) - return; QString newMasternodeCountString = getMasternodeCountString(); if (cachedMasternodeCountString != newMasternodeCountString) diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 5fb1573edcf0..a1c94fea0deb 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -91,6 +91,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco { QString strHTML; + WaitForLock2(cs_main, wallet->cs_wallet); LOCK2(cs_main, wallet->cs_wallet); strHTML.reserve(4000); strHTML += ""; diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index bd5257015bfe..44b5c5a14822 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -77,6 +77,7 @@ class TransactionTablePriv qDebug() << "TransactionTablePriv::refreshWallet"; cachedWallet.clear(); { + WaitForLock2(cs_main, wallet->cs_wallet); LOCK2(cs_main, wallet->cs_wallet); for(std::map::iterator it = wallet->mapWallet.begin(); it != wallet->mapWallet.end(); ++it) { @@ -126,6 +127,7 @@ class TransactionTablePriv } if(showTransaction) { + WaitForLock2(cs_main, wallet->cs_wallet); LOCK2(cs_main, wallet->cs_wallet); // Find transaction in wallet std::map::iterator mi = wallet->mapWallet.find(hash); @@ -208,6 +210,7 @@ class TransactionTablePriv QString describe(TransactionRecord *rec, int unit) { { + WaitForLock2(cs_main, wallet->cs_wallet); LOCK2(cs_main, wallet->cs_wallet); std::map::iterator mi = wallet->mapWallet.find(rec->hash); if(mi != wallet->mapWallet.end()) diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index e318954bc351..5bb7d73c1547 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -275,6 +275,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact } { + WaitForLock2(cs_main, wallet->cs_wallet); LOCK2(cs_main, wallet->cs_wallet); transaction.newPossibleKeyChange(wallet); @@ -323,6 +324,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran } { + WaitForLock2(cs_main, wallet->cs_wallet); LOCK2(cs_main, wallet->cs_wallet); CWalletTx *newTx = transaction.getTransaction(); QList recipients = transaction.getRecipients(); @@ -367,6 +369,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran CTxDestination dest = CBitcoinAddress(strAddress).Get(); std::string strLabel = rcp.label.toStdString(); { + WaitForLock(wallet->cs_wallet); LOCK(wallet->cs_wallet); std::map::iterator mi = wallet->mapAddressBook.find(dest); @@ -466,6 +469,7 @@ bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureStri { bool retval; { + WaitForLock(wallet->cs_wallet); LOCK(wallet->cs_wallet); wallet->Lock(); // Make sure wallet is locked before attempting pass change retval = wallet->ChangeWalletPassphrase(oldPass, newPass); @@ -608,6 +612,7 @@ bool WalletModel::getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const // returns a list of COutputs from COutPoints void WalletModel::getOutputs(const std::vector& vOutpoints, std::vector& vOutputs) { + WaitForLock2(cs_main, wallet->cs_wallet); LOCK2(cs_main, wallet->cs_wallet); BOOST_FOREACH(const COutPoint& outpoint, vOutpoints) { @@ -621,6 +626,7 @@ void WalletModel::getOutputs(const std::vector& vOutpoints, std::vect bool WalletModel::isSpent(const COutPoint& outpoint) const { + WaitForLock2(cs_main, wallet->cs_wallet); LOCK2(cs_main, wallet->cs_wallet); return wallet->IsSpent(outpoint.hash, outpoint.n); } @@ -631,6 +637,7 @@ void WalletModel::listCoins(std::map >& mapCoins) std::vector vCoins; wallet->AvailableCoins(vCoins); + WaitForLock2(cs_main, wallet->cs_wallet); LOCK2(cs_main, wallet->cs_wallet); // ListLockedCoins, mapWallet std::vector vLockedCoins; wallet->ListLockedCoins(vLockedCoins); @@ -665,30 +672,35 @@ void WalletModel::listCoins(std::map >& mapCoins) bool WalletModel::isLockedCoin(uint256 hash, unsigned int n) const { + WaitForLock2(cs_main, wallet->cs_wallet); LOCK2(cs_main, wallet->cs_wallet); return wallet->IsLockedCoin(hash, n); } void WalletModel::lockCoin(COutPoint& output) { + WaitForLock2(cs_main, wallet->cs_wallet); LOCK2(cs_main, wallet->cs_wallet); wallet->LockCoin(output); } void WalletModel::unlockCoin(COutPoint& output) { + WaitForLock2(cs_main, wallet->cs_wallet); LOCK2(cs_main, wallet->cs_wallet); wallet->UnlockCoin(output); } void WalletModel::listLockedCoins(std::vector& vOutpts) { + WaitForLock2(cs_main, wallet->cs_wallet); LOCK2(cs_main, wallet->cs_wallet); wallet->ListLockedCoins(vOutpts); } void WalletModel::loadReceiveRequests(std::vector& vReceiveRequests) { + WaitForLock(wallet->cs_wallet); LOCK(wallet->cs_wallet); BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, wallet->mapAddressBook) BOOST_FOREACH(const PAIRTYPE(std::string, std::string)& item2, item.second.destdata) @@ -704,6 +716,7 @@ bool WalletModel::saveReceiveRequest(const std::string &sAddress, const int64_t ss << nId; std::string key = "rr" + ss.str(); // "rr" prefix = "receive request" in destdata + WaitForLock(wallet->cs_wallet); LOCK(wallet->cs_wallet); if (sRequest.empty()) return wallet->EraseDestData(dest, key); diff --git a/src/rest.cpp b/src/rest.cpp index 6329b44c5355..b15649c90fd4 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -106,6 +106,7 @@ static bool rest_block(AcceptedConnection* conn, CBlock block; CBlockIndex* pblockindex = NULL; { + WaitForLock(cs_main); LOCK(cs_main); if (mapBlockIndex.count(hash) == 0) throw RESTERR(HTTP_NOT_FOUND, hashStr + " not found"); diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 8ff4ffc80e37..0e0d8db93497 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -691,6 +691,7 @@ Value invalidateblock(const Array& params, bool fHelp) CValidationState state; { + WaitForLock(cs_main); LOCK(cs_main); if (mapBlockIndex.count(hash) == 0) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); @@ -730,6 +731,7 @@ Value reconsiderblock(const Array& params, bool fHelp) CValidationState state; { + WaitForLock(cs_main); LOCK(cs_main); if (mapBlockIndex.count(hash) == 0) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index a856ce6923ee..a0333e7660a6 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -164,6 +164,7 @@ Value setgenerate(const Array& params, bool fHelp) CReserveKey reservekey(pwalletMain); { // Don't keep cs_main locked + WaitForLock(cs_main); LOCK(cs_main); nHeightStart = chainActive.Height(); nHeight = nHeightStart; @@ -178,6 +179,7 @@ Value setgenerate(const Array& params, bool fHelp) throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet keypool empty"); CBlock *pblock = &pblocktemplate->block; { + WaitForLock(cs_main); LOCK(cs_main); IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce); } @@ -668,6 +670,7 @@ Value submitblock(const Array& params, bool fHelp) uint256 hash = block.GetHash(); bool fBlockPresent = false; { + WaitForLock(cs_main); LOCK(cs_main); BlockMap::iterator mi = mapBlockIndex.find(hash); if (mi != mapBlockIndex.end()) { diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index a8f51fa6122d..5c4b173836dc 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -35,6 +35,7 @@ Value getconnectioncount(const Array& params, bool fHelp) + HelpExampleRpc("getconnectioncount", "") ); + WaitForLock(cs_vNodes); LOCK(cs_vNodes); return (int)vNodes.size(); } @@ -53,6 +54,7 @@ Value ping(const Array& params, bool fHelp) ); // Request that each node send a ping during next message processing pass + WaitForLock(cs_vNodes); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pNode, vNodes) { pNode->fPingQueued = true; @@ -65,6 +67,7 @@ static void CopyNodeStats(std::vector& vstats) { vstats.clear(); + WaitForLock(cs_vNodes); LOCK(cs_vNodes); vstats.reserve(vNodes.size()); BOOST_FOREACH(CNode* pnode, vNodes) { @@ -294,6 +297,7 @@ Value getaddednodeinfo(const Array& params, bool fHelp) } } + WaitForLock(cs_vNodes); LOCK(cs_vNodes); for (list > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++) { diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index d74fe109d5ab..fa61d5795a0f 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -1014,14 +1014,17 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s result = pcmd->actor(params, false); #ifdef ENABLE_WALLET else if (!pwalletMain) { + WaitForLock(cs_main); LOCK(cs_main); result = pcmd->actor(params, false); } else { + WaitForLock2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet); result = pcmd->actor(params, false); } #else // ENABLE_WALLET else { + WaitForLock(cs_main); LOCK(cs_main); result = pcmd->actor(params, false); } diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 844936e80490..d0d31ddd8072 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -469,6 +469,7 @@ Value listaddressgroupings(const Array& params, bool fHelp) addressInfo.push_back(CBitcoinAddress(address).ToString()); addressInfo.push_back(ValueFromAmount(balances[address])); { + WaitForLock(pwalletMain->cs_wallet); LOCK(pwalletMain->cs_wallet); if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end()) addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second.name); diff --git a/src/spork.cpp b/src/spork.cpp index 1ca978c6c0a9..549b8f830006 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -147,6 +147,7 @@ void ReprocessBlocks(int nBlocks) if((*it).second > GetTime() - (nBlocks*60*5)) { BlockMap::iterator mi = mapBlockIndex.find((*it).first); if (mi != mapBlockIndex.end() && (*mi).second) { + WaitForLock(cs_main); LOCK(cs_main); CBlockIndex* pindex = (*mi).second; @@ -161,6 +162,7 @@ void ReprocessBlocks(int nBlocks) CValidationState state; { + WaitForLock(cs_main); LOCK(cs_main); DisconnectBlocksAndReprocess(nBlocks); } diff --git a/src/wallet.cpp b/src/wallet.cpp index 8408c9cb7a4e..632583c404e9 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -67,6 +67,7 @@ std::string COutput::ToString() const const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const { + WaitForLock(cs_wallet); LOCK(cs_wallet); std::map::const_iterator it = mapWallet.find(hash); if (it == mapWallet.end()) @@ -131,6 +132,7 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, if (!fFileBacked) return true; { + WaitForLock(cs_wallet); LOCK(cs_wallet); if (pwalletdbEncryption) return pwalletdbEncryption->WriteCryptedKey(vchPubKey, @@ -240,6 +242,7 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool anonymizeOnly CKeyingMaterial vMasterKey; { + WaitForLock(cs_wallet); LOCK(cs_wallet); BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys) { @@ -278,6 +281,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, } { + WaitForLock(cs_wallet); LOCK(cs_wallet); Lock(); @@ -339,6 +343,7 @@ void CWallet::SetBestChain(const CBlockLocator& loc) bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit) { + WaitForLock(cs_wallet); // nWalletVersion LOCK(cs_wallet); // nWalletVersion if (nWalletVersion >= nVersion) return true; @@ -366,6 +371,7 @@ bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool CWallet::SetMaxVersion(int nVersion) { + WaitForLock(cs_wallet); // nWalletVersion, nWalletMaxVersion LOCK(cs_wallet); // nWalletVersion, nWalletMaxVersion // cannot downgrade below current version if (nWalletVersion > nVersion) @@ -513,6 +519,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) return false; { + WaitForLock(cs_wallet); LOCK(cs_wallet); mapMasterKeys[++nMasterKeyMaxID] = kMasterKey; if (fFileBacked) @@ -619,6 +626,7 @@ CWallet::TxItems CWallet::OrderedTxItems(std::list& acentries, void CWallet::MarkDirty() { { + WaitForLock(cs_wallet); LOCK(cs_wallet); BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) item.second.MarkDirty(); @@ -637,6 +645,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet) } else { + WaitForLock(cs_wallet); LOCK(cs_wallet); // Inserts only if not already there, returns tx inserted or tx found pair::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn)); @@ -770,6 +779,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl void CWallet::SyncTransaction(const CTransaction& tx, const CBlock* pblock) { + WaitForLock2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet); if (!AddToWalletIfInvolvingMe(tx, pblock, true)) return; // Not one of ours @@ -789,6 +799,7 @@ void CWallet::EraseFromWallet(const uint256 &hash) if (!fFileBacked) return; { + WaitForLock(cs_wallet); LOCK(cs_wallet); if (mapWallet.erase(hash)) CWalletDB(strWalletFile).EraseTx(hash); @@ -800,6 +811,7 @@ void CWallet::EraseFromWallet(const uint256 &hash) isminetype CWallet::IsMine(const CTxIn &txin) const { { + WaitForLock(cs_wallet); LOCK(cs_wallet); map::const_iterator mi = mapWallet.find(txin.prevout.hash); if (mi != mapWallet.end()) @@ -815,6 +827,7 @@ isminetype CWallet::IsMine(const CTxIn &txin) const CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const { { + WaitForLock(cs_wallet); LOCK(cs_wallet); map::const_iterator mi = mapWallet.find(txin.prevout.hash); if (mi != mapWallet.end()) @@ -919,6 +932,7 @@ int CWallet::GetRealInputDarksendRounds(CTxIn in, int rounds) const // respect current settings int CWallet::GetInputDarksendRounds(CTxIn in) const { + WaitForLock(cs_wallet); LOCK(cs_wallet); int realDarksendRounds = GetRealInputDarksendRounds(in, 0); return realDarksendRounds > nDarksendRounds ? nDarksendRounds : realDarksendRounds; @@ -927,6 +941,7 @@ int CWallet::GetInputDarksendRounds(CTxIn in) const { bool CWallet::IsDenominated(const CTxIn &txin) const { { + WaitForLock(cs_wallet); LOCK(cs_wallet); map::const_iterator mi = mapWallet.find(txin.prevout.hash); if (mi != mapWallet.end()) @@ -977,6 +992,7 @@ bool CWallet::IsChange(const CTxOut& txout) const if (!ExtractDestination(txout.scriptPubKey, address)) return true; + WaitForLock(cs_wallet); LOCK(cs_wallet); if (!mapAddressBook.count(address)) return true; @@ -995,6 +1011,7 @@ int CWalletTx::GetRequestCount() const // Returns -1 if it wasn't being tracked int nRequests = -1; { + WaitForLock(pwallet->cs_wallet); LOCK(pwallet->cs_wallet); if (IsCoinBase()) { @@ -1102,6 +1119,7 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, CAmount& nReceived, nFee = allFee; } { + WaitForLock(pwallet->cs_wallet); LOCK(pwallet->cs_wallet); BOOST_FOREACH(const COutputEntry& r, listReceived) { @@ -1137,6 +1155,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) CBlockIndex* pindex = pindexStart; { + WaitForLock2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet); // no need to read and scan block, if block was created before @@ -1172,6 +1191,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) void CWallet::ReacceptWalletTransactions() { + WaitForLock2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet); BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) { @@ -1240,6 +1260,7 @@ void CWallet::ResendWalletTransactions() // Rebroadcast any of our txes that aren't in a block yet LogPrintf("ResendWalletTransactions()\n"); { + WaitForLock(cs_wallet); LOCK(cs_wallet); // Sort them in chronological order multimap mapSorted; @@ -1274,6 +1295,7 @@ CAmount CWallet::GetBalance() const { CAmount nTotal = 0; { + WaitForLock2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet); for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { @@ -1292,6 +1314,7 @@ CAmount CWallet::GetAnonymizableBalance() const CAmount nTotal = 0; { + WaitForLock2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet); for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { @@ -1311,6 +1334,7 @@ CAmount CWallet::GetAnonymizedBalance() const CAmount nTotal = 0; { + WaitForLock2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet); for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { @@ -1334,6 +1358,7 @@ double CWallet::GetAverageAnonymizedRounds() const double fCount = 0; { + WaitForLock2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet); for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { @@ -1368,6 +1393,7 @@ CAmount CWallet::GetNormalizedAnonymizedBalance() const CAmount nTotal = 0; { + WaitForLock2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet); for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { @@ -1397,6 +1423,7 @@ CAmount CWallet::GetDenominatedBalance(bool unconfirmed) const CAmount nTotal = 0; { + WaitForLock2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet); for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { @@ -1413,6 +1440,7 @@ CAmount CWallet::GetUnconfirmedBalance() const { CAmount nTotal = 0; { + WaitForLock2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet); for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { @@ -1428,6 +1456,7 @@ CAmount CWallet::GetImmatureBalance() const { CAmount nTotal = 0; { + WaitForLock2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet); for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { @@ -1442,6 +1471,7 @@ CAmount CWallet::GetWatchOnlyBalance() const { CAmount nTotal = 0; { + WaitForLock2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet); for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { @@ -1458,6 +1488,7 @@ CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const { CAmount nTotal = 0; { + WaitForLock2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet); for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { @@ -1473,6 +1504,7 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const { CAmount nTotal = 0; { + WaitForLock2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet); for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { @@ -1491,6 +1523,7 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const vCoins.clear(); { + WaitForLock2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet); for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { @@ -1939,6 +1972,7 @@ int CWallet::CountInputsWithAmount(int64_t nInputAmount) { int64_t nTotal = 0; { + WaitForLock(cs_wallet); LOCK(cs_wallet); for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { @@ -2124,6 +2158,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, CMutableTransaction txNew; { + WaitForLock2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet); { nFeeRet = 0; @@ -2320,6 +2355,7 @@ bool CWallet::CreateTransaction(CScript scriptPubKey, const CAmount& nValue, bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, std::string strCommand) { { + WaitForLock2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet); LogPrintf("CommitTransaction:\n%s", wtxNew.ToString()); { @@ -2434,6 +2470,7 @@ string CWallet::PrepareDarksendDenominate(int minRounds, int maxRounds) LogPrintf("PrepareDarksendDenominate - preparing darksend denominate . Got: %d \n", nValueIn); + WaitForLock(cs_wallet); LOCK(cs_wallet); BOOST_FOREACH(CTxIn v, vCoins) LockCoin(v.prevout); @@ -2533,6 +2570,7 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) { if (CDB::Rewrite(strWalletFile, "\x04pool")) { + WaitForLock(cs_wallet); LOCK(cs_wallet); setKeyPool.clear(); // Note: can't top-up keypool here, because wallet is locked. @@ -2560,6 +2598,7 @@ DBErrors CWallet::ZapWalletTx(std::vector& vWtx) { if (CDB::Rewrite(strWalletFile, "\x04pool")) { + WaitForLock(cs_wallet); LOCK(cs_wallet); setKeyPool.clear(); // Note: can't top-up keypool here, because wallet is locked. @@ -2579,6 +2618,7 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const string& strNam { bool fUpdated = false; { + WaitForLock(cs_wallet); LOCK(cs_wallet); // mapAddressBook std::map::iterator mi = mapAddressBook.find(address); fUpdated = mi != mapAddressBook.end(); @@ -2598,6 +2638,7 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const string& strNam bool CWallet::DelAddressBook(const CTxDestination& address) { { + WaitForLock(cs_wallet); LOCK(cs_wallet); // mapAddressBook if(fFileBacked) @@ -2638,6 +2679,7 @@ bool CWallet::SetDefaultKey(const CPubKey &vchPubKey) bool CWallet::NewKeyPool() { { + WaitForLock(cs_wallet); LOCK(cs_wallet); CWalletDB walletdb(strWalletFile); BOOST_FOREACH(int64_t nIndex, setKeyPool) @@ -2662,6 +2704,7 @@ bool CWallet::NewKeyPool() bool CWallet::TopUpKeyPool(unsigned int kpSize) { { + WaitForLock(cs_wallet); LOCK(cs_wallet); if (IsLocked()) @@ -2698,6 +2741,7 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool) nIndex = -1; keypool.vchPubKey = CPubKey(); { + WaitForLock(cs_wallet); LOCK(cs_wallet); if (!IsLocked()) @@ -2735,6 +2779,7 @@ void CWallet::ReturnKey(int64_t nIndex) { // Return to key pool { + WaitForLock(cs_wallet); LOCK(cs_wallet); setKeyPool.insert(nIndex); } @@ -2746,6 +2791,7 @@ bool CWallet::GetKeyFromPool(CPubKey& result) int64_t nIndex = 0; CKeyPool keypool; { + WaitForLock(cs_wallet); LOCK(cs_wallet); ReserveKeyFromKeyPool(nIndex, keypool); if (nIndex == -1) @@ -2776,6 +2822,7 @@ std::map CWallet::GetAddressBalances() map balances; { + WaitForLock(cs_wallet); LOCK(cs_wallet); BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet) { @@ -2906,6 +2953,7 @@ set< set > CWallet::GetAddressGroupings() set CWallet::GetAccountAddresses(string strAccount) const { + WaitForLock(cs_wallet); LOCK(cs_wallet); set result; BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, mapAddressBook) @@ -2957,6 +3005,7 @@ void CWallet::GetAllReserveKeys(set& setAddress) const CWalletDB walletdb(strWalletFile); + WaitForLock2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet); BOOST_FOREACH(const int64_t& id, setKeyPool) { @@ -2974,6 +3023,7 @@ void CWallet::GetAllReserveKeys(set& setAddress) const bool CWallet::UpdatedTransaction(const uint256 &hashTx) { { + WaitForLock(cs_wallet); LOCK(cs_wallet); // Only notify UI if this transaction is in this wallet map::const_iterator mi = mapWallet.find(hashTx); diff --git a/src/wallet.h b/src/wallet.h index 106c919afa50..8b6e3059096f 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -435,6 +435,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void Inventory(const uint256 &hash) { { + WaitForLock(cs_wallet); LOCK(cs_wallet); std::map::iterator mi = mapRequestCount.find(hash); if (mi != mapRequestCount.end()) @@ -457,7 +458,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool SetMaxVersion(int nVersion); //! get the current wallet format (the oldest client version guaranteed to understand this wallet) - int GetVersion() { LOCK(cs_wallet); return nWalletVersion; } + int GetVersion() { WaitForLock(cs_wallet); LOCK(cs_wallet); return nWalletVersion; } //! Get wallet transactions that conflict with given transaction (spend same outputs) std::set GetConflicts(const uint256& txid) const; diff --git a/src/walletdb.cpp b/src/walletdb.cpp index 8c9b31df400b..9b2c56a473ec 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -251,6 +251,7 @@ void CWalletDB::ListAccountCreditDebit(const string& strAccount, listcs_wallet); LOCK(pwallet->cs_wallet); // Old wallets didn't have any defined order for transactions // Probably a bad idea to change the output of this @@ -612,6 +613,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) DBErrors result = DB_LOAD_OK; try { + WaitForLock(pwallet->cs_wallet); LOCK(pwallet->cs_wallet); int nMinVersion = 0; if (Read((string)"minversion", nMinVersion)) @@ -712,6 +714,7 @@ DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, vector& vTxHash, vec DBErrors result = DB_LOAD_OK; try { + WaitForLock(pwallet->cs_wallet); LOCK(pwallet->cs_wallet); int nMinVersion = 0; if (Read((string)"minversion", nMinVersion))