Skip to content

Commit 0dec5b5

Browse files
author
MarcoFalke
committed
Merge #13081: wallet: Add compile time checking for cs_wallet runtime locking assertions
66b0b1b Add compile time checking for all cs_wallet runtime locking assertions (practicalswift) Pull request description: Add compile time checking for `cs_wallet` runtime locking assertions. This PR is a subset of #12665. The PR was broken up to make reviewing easier. The intention is that literally all `EXCLUSIVE_LOCKS_REQUIRED`/`LOCKS_EXCLUDED`:s added in this PR should follow either directly or indirectly from `AssertLockHeld(…)`/`AssertLockNotHeld(…)`:s already existing in the repo. Consider the case where function `A(…)` contains `AssertLockHeld(cs_foo)` (without first locking `cs_foo` in `A`), and that `B(…)` calls `A(…)` (without first locking `cs_main`): * It _directly_ follows that: `A(…)` should have an `EXCLUSIVE_LOCKS_REQUIRED(cs_foo)` annotation. * It _indirectly_ follows that: `B(…)` should have an `EXCLUSIVE_LOCKS_REQUIRED(cs_foo)` annotation. Tree-SHA512: d561d89e98a823922107e56dbd493f0f82e22edac91e51e6422f17daf2b446a70c143b7b157ca618fadd33d0ec63eb7a57dde5a83bfdf1fc19d71459b43e21fd
2 parents 7cc1bd3 + 66b0b1b commit 0dec5b5

File tree

4 files changed

+37
-37
lines changed

4 files changed

+37
-37
lines changed

src/wallet/feebumper.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
//! Check whether transaction has descendant in wallet or mempool, or has been
2020
//! mined, or conflicts with a mined transaction. Return a feebumper::Result.
21-
static feebumper::Result PreconditionChecks(const CWallet* wallet, const CWalletTx& wtx, std::vector<std::string>& errors)
21+
static feebumper::Result PreconditionChecks(const CWallet* wallet, const CWalletTx& wtx, std::vector<std::string>& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet)
2222
{
2323
if (wallet->HasWalletSpend(wtx.GetHash())) {
2424
errors.push_back("Transaction has descendants in the wallet");

src/wallet/rpcdump.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ UniValue abortrescan(const JSONRPCRequest& request)
209209
}
210210

211211
static void ImportAddress(CWallet*, const CTxDestination& dest, const std::string& strLabel);
212-
static void ImportScript(CWallet* const pwallet, const CScript& script, const std::string& strLabel, bool isRedeemScript)
212+
static void ImportScript(CWallet* const pwallet, const CScript& script, const std::string& strLabel, bool isRedeemScript) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
213213
{
214214
if (!isRedeemScript && ::IsMine(*pwallet, script) == ISMINE_SPENDABLE) {
215215
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
@@ -235,7 +235,7 @@ static void ImportScript(CWallet* const pwallet, const CScript& script, const st
235235
}
236236
}
237237

238-
static void ImportAddress(CWallet* const pwallet, const CTxDestination& dest, const std::string& strLabel)
238+
static void ImportAddress(CWallet* const pwallet, const CTxDestination& dest, const std::string& strLabel) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
239239
{
240240
CScript script = GetScriptForDestination(dest);
241241
ImportScript(pwallet, script, strLabel, false);
@@ -811,7 +811,7 @@ UniValue dumpwallet(const JSONRPCRequest& request)
811811
}
812812

813813

814-
static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp)
814+
static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
815815
{
816816
try {
817817
bool success = false;

src/wallet/wallet.h

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -710,13 +710,13 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
710710

711711
/* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected.
712712
* Should be called with pindexBlock and posInBlock if this is for a transaction that is included in a block. */
713-
void SyncTransaction(const CTransactionRef& tx, const CBlockIndex *pindex = nullptr, int posInBlock = 0);
713+
void SyncTransaction(const CTransactionRef& tx, const CBlockIndex *pindex = nullptr, int posInBlock = 0) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
714714

715715
/* the HD chain data model (external chain counters) */
716716
CHDChain hdChain;
717717

718718
/* HD derive new child key (on internal or external chain) */
719-
void DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey& secret, bool internal = false);
719+
void DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey& secret, bool internal = false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
720720

721721
std::set<int64_t> setInternalKeyPool;
722722
std::set<int64_t> setExternalKeyPool;
@@ -735,7 +735,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
735735
* of the other AddWatchOnly which accepts a timestamp and sets
736736
* nTimeFirstKey more intelligently for more efficient rescans.
737737
*/
738-
bool AddWatchOnly(const CScript& dest) override;
738+
bool AddWatchOnly(const CScript& dest) override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
739739

740740
/**
741741
* Wallet filename from wallet=<path> command line or config option.
@@ -786,7 +786,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
786786
*/
787787
const std::string& GetName() const { return m_name; }
788788

789-
void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool);
789+
void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
790790
void MarkPreSplitKeys();
791791

792792
// Map from Key ID to key metadata.
@@ -828,12 +828,12 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
828828
const CWalletTx* GetWalletTx(const uint256& hash) const;
829829

830830
//! check whether we are allowed to upgrade (or already support) to the named feature
831-
bool CanSupportFeature(enum WalletFeature wf) const { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; }
831+
bool CanSupportFeature(enum WalletFeature wf) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; }
832832

833833
/**
834834
* populate vCoins with vector of available COutputs.
835835
*/
836-
void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0, const int nMinDepth = 0, const int nMaxDepth = 9999999) const;
836+
void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0, const int nMinDepth = 0, const int nMaxDepth = 9999999) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
837837

838838
/**
839839
* Return list of available coins and locked coins grouped by non-change output address.
@@ -856,11 +856,11 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
856856

857857
bool IsSpent(const uint256& hash, unsigned int n) const;
858858

859-
bool IsLockedCoin(uint256 hash, unsigned int n) const;
860-
void LockCoin(const COutPoint& output);
861-
void UnlockCoin(const COutPoint& output);
862-
void UnlockAllCoins();
863-
void ListLockedCoins(std::vector<COutPoint>& vOutpts) const;
859+
bool IsLockedCoin(uint256 hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
860+
void LockCoin(const COutPoint& output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
861+
void UnlockCoin(const COutPoint& output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
862+
void UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
863+
void ListLockedCoins(std::vector<COutPoint>& vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
864864

865865
/*
866866
* Rescan abort properties
@@ -873,18 +873,18 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
873873
* keystore implementation
874874
* Generate a new key
875875
*/
876-
CPubKey GenerateNewKey(WalletBatch& batch, bool internal = false);
876+
CPubKey GenerateNewKey(WalletBatch& batch, bool internal = false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
877877
//! Adds a key to the store, and saves it to disk.
878-
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override;
879-
bool AddKeyPubKeyWithDB(WalletBatch &batch,const CKey& key, const CPubKey &pubkey);
878+
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
879+
bool AddKeyPubKeyWithDB(WalletBatch &batch,const CKey& key, const CPubKey &pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
880880
//! Adds a key to the store, without saving it to disk (used by LoadWallet)
881881
bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); }
882882
//! Load metadata (used by LoadWallet)
883-
bool LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata);
884-
bool LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata);
883+
bool LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
884+
bool LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
885885

886-
bool LoadMinVersion(int nVersion) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
887-
void UpdateTimeFirstKey(int64_t nCreateTime);
886+
bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
887+
void UpdateTimeFirstKey(int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
888888

889889
//! Adds an encrypted key to the store, and saves it to disk.
890890
bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) override;
@@ -905,8 +905,8 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
905905
std::vector<std::string> GetDestValues(const std::string& prefix) const;
906906

907907
//! Adds a watch-only address to the store, and saves it to disk.
908-
bool AddWatchOnly(const CScript& dest, int64_t nCreateTime);
909-
bool RemoveWatchOnly(const CScript &dest) override;
908+
bool AddWatchOnly(const CScript& dest, int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
909+
bool RemoveWatchOnly(const CScript &dest) override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
910910
//! Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
911911
bool LoadWatchOnly(const CScript &dest);
912912

@@ -917,16 +917,16 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
917917
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
918918
bool EncryptWallet(const SecureString& strWalletPassphrase);
919919

920-
void GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) const;
920+
void GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
921921
unsigned int ComputeTimeSmart(const CWalletTx& wtx) const;
922922

923923
/**
924924
* Increment the next transaction order id
925925
* @return next transaction order id
926926
*/
927-
int64_t IncOrderPosNext(WalletBatch *batch = nullptr);
927+
int64_t IncOrderPosNext(WalletBatch *batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
928928
DBErrors ReorderTransactions();
929-
bool AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment = "");
929+
bool AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment = "") EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
930930
bool GetLabelDestination(CTxDestination &dest, const std::string& label, bool bForceNew = false);
931931

932932
void MarkDirty();
@@ -935,7 +935,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
935935
void TransactionAddedToMempool(const CTransactionRef& tx) override;
936936
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) override;
937937
void BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) override;
938-
bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate);
938+
bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
939939
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update);
940940
CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, const WalletRescanReserver& reserver, bool fUpdate = false);
941941
void TransactionRemovedFromMempool(const CTransactionRef &ptx) override;
@@ -959,7 +959,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
959959
* calling CreateTransaction();
960960
*/
961961
bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl);
962-
bool SignTransaction(CMutableTransaction& tx);
962+
bool SignTransaction(CMutableTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
963963

964964
/**
965965
* Create a new transaction paying the recipients with a set of coins
@@ -999,7 +999,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
999999
OutputType m_default_change_type{DEFAULT_CHANGE_TYPE};
10001000

10011001
bool NewKeyPool();
1002-
size_t KeypoolCountExternalKeys();
1002+
size_t KeypoolCountExternalKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
10031003
bool TopUpKeyPool(unsigned int kpSize = 0);
10041004
void ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal);
10051005
void KeepKey(int64_t nIndex);
@@ -1009,10 +1009,10 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
10091009
/**
10101010
* Marks all keys in the keypool up to and including reserve_key as used.
10111011
*/
1012-
void MarkReserveKeysAsUsed(int64_t keypool_id);
1012+
void MarkReserveKeysAsUsed(int64_t keypool_id) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
10131013
const std::map<CKeyID, int64_t>& GetAllReserveKeys() const { return m_pool_key_to_index; }
10141014

1015-
std::set< std::set<CTxDestination> > GetAddressGroupings();
1015+
std::set<std::set<CTxDestination>> GetAddressGroupings() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
10161016
std::map<CTxDestination, CAmount> GetAddressBalances();
10171017

10181018
std::set<CTxDestination> GetLabelAddresses(const std::string& label) const;
@@ -1040,7 +1040,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
10401040

10411041
DBErrors LoadWallet(bool& fFirstRunRet);
10421042
DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
1043-
DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut);
1043+
DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
10441044

10451045
bool SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& purpose);
10461046

@@ -1060,7 +1060,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
10601060

10611061
void GetScriptForMining(std::shared_ptr<CReserveScript> &script);
10621062

1063-
unsigned int GetKeyPoolSize()
1063+
unsigned int GetKeyPoolSize() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
10641064
{
10651065
AssertLockHeld(cs_wallet); // set{Ex,In}ternalKeyPool
10661066
return setInternalKeyPool.size() + setExternalKeyPool.size();
@@ -1079,7 +1079,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
10791079
std::set<uint256> GetConflicts(const uint256& txid) const;
10801080

10811081
//! Check if a given transaction has any of its outputs spent by another transaction in the wallet
1082-
bool HasWalletSpend(const uint256& txid) const;
1082+
bool HasWalletSpend(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
10831083

10841084
//! Flush wallet (bitdb flush)
10851085
void Flush(bool shutdown=false);
@@ -1156,7 +1156,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
11561156
* Obviously holding cs_main/cs_wallet when going into this call may cause
11571157
* deadlock
11581158
*/
1159-
void BlockUntilSyncedToCurrentChain();
1159+
void BlockUntilSyncedToCurrentChain() LOCKS_EXCLUDED(cs_wallet);
11601160

11611161
/**
11621162
* Explicitly make the wallet learn the related scripts for outputs to the

src/wallet/walletdb.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ class CWalletScanState {
248248

249249
static bool
250250
ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
251-
CWalletScanState &wss, std::string& strType, std::string& strErr)
251+
CWalletScanState &wss, std::string& strType, std::string& strErr) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
252252
{
253253
try {
254254
// Unserialize

0 commit comments

Comments
 (0)