Document cs_wallet lock and add AssertLockHeld

Add locking assertions to wallet to all methods that
access internal fields and do not aquire the cs_wallet mutex.
This commit is contained in:
Wladimir J. van der Laan 2013-12-12 08:07:59 +01:00
parent 19a5676280
commit 956916806a
2 changed files with 28 additions and 3 deletions

View file

@ -33,6 +33,7 @@ struct CompareValueOnly
CPubKey CWallet::GenerateNewKey() CPubKey CWallet::GenerateNewKey()
{ {
AssertLockHeld(cs_wallet); // mapKeyMetadata
bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
RandAddSeedPerfmon(); RandAddSeedPerfmon();
@ -58,6 +59,7 @@ CPubKey CWallet::GenerateNewKey()
bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey) bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
{ {
AssertLockHeld(cs_wallet); // mapKeyMetadata
if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey)) if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
return false; return false;
if (!fFileBacked) if (!fFileBacked)
@ -93,6 +95,7 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta) bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta)
{ {
AssertLockHeld(cs_wallet); // mapKeyMetadata
if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey)) if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey))
nTimeFirstKey = meta.nCreateTime; nTimeFirstKey = meta.nCreateTime;
@ -200,6 +203,7 @@ public:
bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit) bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit)
{ {
AssertLockHeld(cs_wallet); // nWalletVersion
if (nWalletVersion >= nVersion) if (nWalletVersion >= nVersion)
return true; return true;
@ -233,6 +237,7 @@ bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn,
bool CWallet::SetMaxVersion(int nVersion) bool CWallet::SetMaxVersion(int nVersion)
{ {
AssertLockHeld(cs_wallet); // nWalletVersion, nWalletMaxVersion
// cannot downgrade below current version // cannot downgrade below current version
if (nWalletVersion > nVersion) if (nWalletVersion > nVersion)
return false; return false;
@ -325,6 +330,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb) int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
{ {
AssertLockHeld(cs_wallet); // nOrderPosNext
int64_t nRet = nOrderPosNext++; int64_t nRet = nOrderPosNext++;
if (pwalletdb) { if (pwalletdb) {
pwalletdb->WriteOrderPosNext(nOrderPosNext); pwalletdb->WriteOrderPosNext(nOrderPosNext);
@ -336,6 +342,7 @@ int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount) CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount)
{ {
AssertLockHeld(cs_wallet); // mapWallet
CWalletDB walletdb(strWalletFile); CWalletDB walletdb(strWalletFile);
// First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap. // First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap.
@ -1482,6 +1489,7 @@ string CWallet::SendMoneyToDestination(const CTxDestination& address, int64_t nV
DBErrors CWallet::LoadWallet(bool& fFirstRunRet) DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
{ {
AssertLockHeld(cs_wallet); // setKeyPool
if (!fFileBacked) if (!fFileBacked)
return DB_LOAD_OK; return DB_LOAD_OK;
fFirstRunRet = false; fFirstRunRet = false;
@ -1507,6 +1515,7 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
bool CWallet::SetAddressBook(const CTxDestination& address, const string& strName, const string& strPurpose) bool CWallet::SetAddressBook(const CTxDestination& address, const string& strName, const string& strPurpose)
{ {
AssertLockHeld(cs_wallet); // mapAddressBook
std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address); std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address);
mapAddressBook[address].name = strName; mapAddressBook[address].name = strName;
if (!strPurpose.empty()) /* update purpose only if requested */ if (!strPurpose.empty()) /* update purpose only if requested */
@ -1523,6 +1532,7 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const string& strNam
bool CWallet::DelAddressBook(const CTxDestination& address) bool CWallet::DelAddressBook(const CTxDestination& address)
{ {
AssertLockHeld(cs_wallet); // mapAddressBook
mapAddressBook.erase(address); mapAddressBook.erase(address);
NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), "", CT_DELETED); NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), "", CT_DELETED);
if (!fFileBacked) if (!fFileBacked)
@ -1736,6 +1746,7 @@ std::map<CTxDestination, int64_t> CWallet::GetAddressBalances()
set< set<CTxDestination> > CWallet::GetAddressGroupings() set< set<CTxDestination> > CWallet::GetAddressGroupings()
{ {
AssertLockHeld(cs_wallet); // mapWallet
set< set<CTxDestination> > groupings; set< set<CTxDestination> > groupings;
set<CTxDestination> grouping; set<CTxDestination> grouping;
@ -1828,6 +1839,7 @@ set< set<CTxDestination> > CWallet::GetAddressGroupings()
set<CTxDestination> CWallet::GetAccountAddresses(string strAccount) const set<CTxDestination> CWallet::GetAccountAddresses(string strAccount) const
{ {
AssertLockHeld(cs_wallet); // mapWallet
set<CTxDestination> result; set<CTxDestination> result;
BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, mapAddressBook) BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, mapAddressBook)
{ {
@ -1909,21 +1921,25 @@ void CWallet::UpdatedTransaction(const uint256 &hashTx)
void CWallet::LockCoin(COutPoint& output) void CWallet::LockCoin(COutPoint& output)
{ {
AssertLockHeld(cs_wallet); // setLockedCoins
setLockedCoins.insert(output); setLockedCoins.insert(output);
} }
void CWallet::UnlockCoin(COutPoint& output) void CWallet::UnlockCoin(COutPoint& output)
{ {
AssertLockHeld(cs_wallet); // setLockedCoins
setLockedCoins.erase(output); setLockedCoins.erase(output);
} }
void CWallet::UnlockAllCoins() void CWallet::UnlockAllCoins()
{ {
AssertLockHeld(cs_wallet); // setLockedCoins
setLockedCoins.clear(); setLockedCoins.clear();
} }
bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
{ {
AssertLockHeld(cs_wallet); // setLockedCoins
COutPoint outpt(hash, n); COutPoint outpt(hash, n);
return (setLockedCoins.count(outpt) > 0); return (setLockedCoins.count(outpt) > 0);
@ -1931,6 +1947,7 @@ bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts) void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
{ {
AssertLockHeld(cs_wallet); // setLockedCoins
for (std::set<COutPoint>::iterator it = setLockedCoins.begin(); for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
it != setLockedCoins.end(); it++) { it != setLockedCoins.end(); it++) {
COutPoint outpt = (*it); COutPoint outpt = (*it);
@ -1939,6 +1956,7 @@ void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
} }
void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const { void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const {
AssertLockHeld(cs_wallet); // mapKeyMetadata
mapKeyBirth.clear(); mapKeyBirth.clear();
// get birth times for keys with metadata // get birth times for keys with metadata

View file

@ -102,6 +102,11 @@ private:
int64_t nLastResend; int64_t nLastResend;
public: public:
/// Main wallet lock.
/// This lock protects all the fields added by CWallet
/// except for:
/// fFileBacked (immutable after instantiation)
/// strWalletFile (immutable after instantiation)
mutable CCriticalSection cs_wallet; mutable CCriticalSection cs_wallet;
bool fFileBacked; bool fFileBacked;
@ -151,10 +156,11 @@ public:
int64_t nTimeFirstKey; int64_t nTimeFirstKey;
// check whether we are allowed to upgrade (or already support) to the named feature // check whether we are allowed to upgrade (or already support) to the named feature
bool CanSupportFeature(enum WalletFeature wf) { return nWalletMaxVersion >= wf; } bool CanSupportFeature(enum WalletFeature wf) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; }
void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL) const; void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL) const;
bool SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet) const; bool SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet) const;
bool IsLockedCoin(uint256 hash, unsigned int n) const; bool IsLockedCoin(uint256 hash, unsigned int n) const;
void LockCoin(COutPoint& output); void LockCoin(COutPoint& output);
void UnlockCoin(COutPoint& output); void UnlockCoin(COutPoint& output);
@ -171,7 +177,7 @@ public:
// Load metadata (used by LoadWallet) // Load metadata (used by LoadWallet)
bool LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &metadata); bool LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &metadata);
bool LoadMinVersion(int nVersion) { nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; } bool LoadMinVersion(int nVersion) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
// Adds an encrypted key to the store, and saves it to disk. // Adds an encrypted key to the store, and saves it to disk.
bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret); bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
@ -320,6 +326,7 @@ public:
unsigned int GetKeyPoolSize() unsigned int GetKeyPoolSize()
{ {
AssertLockHeld(cs_wallet); // setKeyPool
return setKeyPool.size(); return setKeyPool.size();
} }
@ -332,7 +339,7 @@ public:
bool SetMaxVersion(int nVersion); bool SetMaxVersion(int nVersion);
// get the current wallet format (the oldest client version guaranteed to understand this wallet) // get the current wallet format (the oldest client version guaranteed to understand this wallet)
int GetVersion() { return nWalletVersion; } int GetVersion() { AssertLockHeld(cs_wallet); return nWalletVersion; }
/** Address book entry changed. /** Address book entry changed.
* @note called with lock cs_wallet held. * @note called with lock cs_wallet held.