diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -122,8 +122,7 @@ { auto spk_man = wallet->GetLegacyScriptPubKeyMan(); auto locked_chain = wallet->chain().lock(); - LOCK(wallet->cs_wallet); - AssertLockHeld(spk_man->cs_wallet); + LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore); wallet->SetAddressBook( GetDestinationForKey(test.coinbaseKey.GetPubKey(), wallet->m_default_address_type), diff --git a/src/test/util/wallet.cpp b/src/test/util/wallet.cpp --- a/src/test/util/wallet.cpp +++ b/src/test/util/wallet.cpp @@ -28,8 +28,7 @@ void importaddress(CWallet &wallet, const std::string &address) { auto spk_man = wallet.GetLegacyScriptPubKeyMan(); - LOCK(wallet.cs_wallet); - AssertLockHeld(spk_man->cs_wallet); + LOCK2(wallet.cs_wallet, spk_man->cs_KeyStore); const auto dest = DecodeDestination(address, wallet.chainParams); assert(IsValidDestination(dest)); const auto script = GetScriptForDestination(dest); diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -842,7 +842,7 @@ LegacyScriptPubKeyMan &spk_man = EnsureLegacyScriptPubKeyMan(*wallet); auto locked_chain = pwallet->chain().lock(); - LOCK(pwallet->cs_wallet); + LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore); EnsureWalletIsUnlocked(pwallet); @@ -898,8 +898,7 @@ LegacyScriptPubKeyMan &spk_man = EnsureLegacyScriptPubKeyMan(*wallet); auto locked_chain = pwallet->chain().lock(); - LOCK(pwallet->cs_wallet); - AssertLockHeld(spk_man.cs_wallet); + LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore); EnsureWalletIsUnlocked(pwallet); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1131,7 +1131,7 @@ LegacyScriptPubKeyMan &spk_man = EnsureLegacyScriptPubKeyMan(*pwallet); auto locked_chain = pwallet->chain().lock(); - LOCK(pwallet->cs_wallet); + LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore); std::string label; if (!request.params[2].isNull()) { @@ -4513,7 +4513,7 @@ } auto locked_chain = pwallet->chain().lock(); - LOCK(pwallet->cs_wallet); + LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore); // Do not do anything to non-HD wallets if (!pwallet->CanSupportFeature(FEATURE_HD)) { diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h --- a/src/wallet/scriptpubkeyman.h +++ b/src/wallet/scriptpubkeyman.h @@ -245,7 +245,7 @@ using WatchOnlySet = std::set; using WatchKeyMap = std::map; - WalletBatch *encrypted_batch GUARDED_BY(cs_wallet) = nullptr; + WalletBatch *encrypted_batch GUARDED_BY(cs_KeyStore) = nullptr; using CryptedKeyMap = std::map>>; @@ -254,7 +254,7 @@ WatchOnlySet setWatchOnly GUARDED_BY(cs_KeyStore); WatchKeyMap mapWatchKeys GUARDED_BY(cs_KeyStore); - int64_t nTimeFirstKey GUARDED_BY(cs_wallet) = 0; + int64_t nTimeFirstKey GUARDED_BY(cs_KeyStore) = 0; bool AddKeyPubKeyInner(const CKey &key, const CPubKey &pubkey); bool AddCryptedKeyInner(const CPubKey &vchPubKey, @@ -269,19 +269,20 @@ * of the other AddWatchOnly which accepts a timestamp and sets * nTimeFirstKey more intelligently for more efficient rescans. */ - bool AddWatchOnly(const CScript &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + bool AddWatchOnly(const CScript &dest) + EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript &dest) - EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); bool AddWatchOnlyInMem(const CScript &dest); //! Adds a watch-only address to the store, and saves it to disk. bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript &dest, int64_t create_time) - EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); //! Adds a key to the store, and saves it to disk. bool AddKeyPubKeyWithDB(WalletBatch &batch, const CKey &key, const CPubKey &pubkey) - EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); void AddKeypoolPubkeyWithDB(const CPubKey &pubkey, const bool internal, WalletBatch &batch); @@ -299,12 +300,12 @@ /* HD derive new child key (on internal or external chain) */ void DeriveNewChildKey(WalletBatch &batch, CKeyMetadata &metadata, CKey &secret, bool internal = false) - EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); - std::set setInternalKeyPool GUARDED_BY(cs_wallet); - std::set setExternalKeyPool GUARDED_BY(cs_wallet); - std::set set_pre_split_keypool GUARDED_BY(cs_wallet); - int64_t m_max_keypool_index GUARDED_BY(cs_wallet) = 0; + std::set setInternalKeyPool GUARDED_BY(cs_KeyStore); + std::set setExternalKeyPool GUARDED_BY(cs_KeyStore); + std::set set_pre_split_keypool GUARDED_BY(cs_KeyStore); + int64_t m_max_keypool_index GUARDED_BY(cs_KeyStore) = 0; std::map m_pool_key_to_index; // Tracks keypool indexes to CKeyIDs of keys that have been taken out of the // keypool but may be returned to it @@ -354,7 +355,7 @@ //! Upgrade stored CKeyMetadata objects to store key origin info as //! KeyOriginInfo - void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + void UpgradeKeyMetadata(); bool IsHDEnabled() const override; @@ -367,8 +368,7 @@ void RewriteDB() override; int64_t GetOldestKeyPoolTime() override; - size_t KeypoolCountExternalKeys() override - EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + size_t KeypoolCountExternalKeys() override; unsigned int GetKeyPoolSize() const override; int64_t GetTimeFirstKey() const override; @@ -378,14 +378,13 @@ bool CanGetAddresses(bool internal = false) override; // Map from Key ID to key metadata. - std::map mapKeyMetadata GUARDED_BY(cs_wallet); + std::map mapKeyMetadata GUARDED_BY(cs_KeyStore); // Map from Script ID to key metadata (for watch-only keys). - std::map m_script_metadata GUARDED_BY(cs_wallet); + std::map m_script_metadata GUARDED_BY(cs_KeyStore); //! Adds a key to the store, and saves it to disk. - bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey) override - EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey) override; //! Adds a key to the store, without saving it to disk (used by LoadWallet) bool LoadKey(const CKey &key, const CPubKey &pubkey); //! Adds an encrypted key to the store, and saves it to disk. @@ -396,18 +395,16 @@ bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector &vchCryptedSecret); void UpdateTimeFirstKey(int64_t nCreateTime) - EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); //! Adds a CScript to the store bool LoadCScript(const CScript &redeemScript); //! Load metadata (used by LoadWallet) - void LoadKeyMetadata(const CKeyID &keyID, const CKeyMetadata &metadata) - EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + void LoadKeyMetadata(const CKeyID &keyID, const CKeyMetadata &metadata); void LoadScriptMetadata(const CScriptID &script_id, - const CKeyMetadata &metadata) - EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + const CKeyMetadata &metadata); //! Generate a new key CPubKey GenerateNewKey(WalletBatch &batch, bool internal = false) - EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); /* Set the HD chain model (chain child index counters) */ void SetHDChain(const CHDChain &chain, bool memonly); @@ -421,10 +418,9 @@ //! Returns whether there are any watch-only things in the wallet bool HaveWatchOnly() const; //! Remove a watch only script from the keystore - bool RemoveWatchOnly(const CScript &dest) - EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + bool RemoveWatchOnly(const CScript &dest); bool AddWatchOnly(const CScript &dest, int64_t nCreateTime) - EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); //! Fetches a pubkey from mapWatchKeys if it exists there bool GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const; @@ -437,26 +433,25 @@ bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const override; //! Load a keypool entry - void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool) - EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool); bool NewKeyPool(); - void MarkPreSplitKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + void MarkPreSplitKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); bool ImportScripts(const std::set scripts, int64_t timestamp) - EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); bool ImportPrivKeys(const std::map &privkey_map, const int64_t timestamp) - EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); bool ImportPubKeys( const std::vector &ordered_pubkeys, const std::map &pubkey_map, const std::map> &key_origins, const bool add_keypool, const bool internal, const int64_t timestamp) - EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); bool ImportScriptPubKeys(const std::set &script_pub_keys, const bool have_solving_data, const int64_t timestamp) - EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); /* Returns true if the wallet can generate new keys */ bool CanGenerateKeys(); @@ -491,7 +486,7 @@ * Marks all keys in the keypool up to and including reserve_key as used. */ void MarkReserveKeysAsUsed(int64_t keypool_id) - EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); const std::map &GetAllReserveKeys() const { return m_pool_key_to_index; } @@ -507,7 +502,6 @@ void WalletLogPrintf(const std::string &fmt, const Params &... parameters) const; CWallet &m_wallet; - RecursiveMutex &cs_wallet; }; #endif // BITCOIN_WALLET_SCRIPTPUBKEYMAN_H diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp --- a/src/wallet/scriptpubkeyman.cpp +++ b/src/wallet/scriptpubkeyman.cpp @@ -15,6 +15,7 @@ bool LegacyScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDestination &dest, std::string &error) { + LOCK(cs_KeyStore); error.clear(); // Generate a new key that is added to wallet @@ -187,7 +188,6 @@ bool LegacyScriptPubKeyMan::Encrypt(const CKeyingMaterial &master_key, WalletBatch *batch) { - AssertLockHeld(cs_wallet); LOCK(cs_KeyStore); encrypted_batch = batch; if (!mapCryptedKeys.empty()) { @@ -222,6 +222,7 @@ CTxDestination &address, int64_t &index, CKeyPool &keypool) { + LOCK(cs_KeyStore); if (!CanGetAddresses(internal)) { return false; } @@ -234,7 +235,7 @@ } void LegacyScriptPubKeyMan::MarkUnusedAddresses(const CScript &script) { - AssertLockHeld(cs_wallet); + LOCK(cs_KeyStore); // extract addresses and check if they match with an unused keypool key for (const auto &keyid : GetAffectedKeys(script, *this)) { std::map::const_iterator mi = @@ -255,7 +256,7 @@ } void LegacyScriptPubKeyMan::UpgradeKeyMetadata() { - AssertLockHeld(cs_wallet); + LOCK(cs_KeyStore); if (m_storage.IsLocked() || m_storage.IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) { return; @@ -310,7 +311,7 @@ } bool LegacyScriptPubKeyMan::CanGetAddresses(bool internal) { - LOCK(cs_wallet); + LOCK(cs_KeyStore); // Check if the keypool has keys bool keypool_has_keys; if (internal && m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) { @@ -326,7 +327,7 @@ } bool LegacyScriptPubKeyMan::Upgrade(int prev_version, bilingual_str &error) { - AssertLockHeld(cs_wallet); + LOCK(cs_KeyStore); bool hd_upgrade = false; bool split_upgrade = false; if (m_storage.CanSupportFeature(FEATURE_HD) && !IsHDEnabled()) { @@ -364,7 +365,7 @@ } void LegacyScriptPubKeyMan::RewriteDB() { - AssertLockHeld(cs_wallet); + LOCK(cs_KeyStore); setInternalKeyPool.clear(); setExternalKeyPool.clear(); m_pool_key_to_index.clear(); @@ -391,7 +392,7 @@ } int64_t LegacyScriptPubKeyMan::GetOldestKeyPoolTime() { - LOCK(cs_wallet); + LOCK(cs_KeyStore); WalletBatch batch(m_storage.GetDatabase()); @@ -411,24 +412,24 @@ } size_t LegacyScriptPubKeyMan::KeypoolCountExternalKeys() { - AssertLockHeld(cs_wallet); + LOCK(cs_KeyStore); return setExternalKeyPool.size() + set_pre_split_keypool.size(); } unsigned int LegacyScriptPubKeyMan::GetKeyPoolSize() const { - AssertLockHeld(cs_wallet); + LOCK(cs_KeyStore); return setInternalKeyPool.size() + setExternalKeyPool.size() + set_pre_split_keypool.size(); } int64_t LegacyScriptPubKeyMan::GetTimeFirstKey() const { - AssertLockHeld(cs_wallet); + LOCK(cs_KeyStore); return nTimeFirstKey; } const CKeyMetadata * LegacyScriptPubKeyMan::GetMetadata(const CTxDestination &dest) const { - AssertLockHeld(cs_wallet); + LOCK(cs_KeyStore); CKeyID key_id = GetKeyForDestination(*this, dest); if (!key_id.IsNull()) { @@ -452,7 +453,7 @@ * are added to the wallet, with the oldest key creation time. */ void LegacyScriptPubKeyMan::UpdateTimeFirstKey(int64_t nCreateTime) { - AssertLockHeld(cs_wallet); + AssertLockHeld(cs_KeyStore); if (nCreateTime <= 1) { // Cannot determine birthday information, so set the wallet birthday to // the beginning of time. @@ -468,6 +469,7 @@ bool LegacyScriptPubKeyMan::AddKeyPubKey(const CKey &secret, const CPubKey &pubkey) { + LOCK(cs_KeyStore); WalletBatch batch(m_storage.GetDatabase()); return LegacyScriptPubKeyMan::AddKeyPubKeyWithDB(batch, secret, pubkey); } @@ -475,7 +477,7 @@ bool LegacyScriptPubKeyMan::AddKeyPubKeyWithDB(WalletBatch &batch, const CKey &secret, const CPubKey &pubkey) { - AssertLockHeld(cs_wallet); + AssertLockHeld(cs_KeyStore); // Make sure we aren't adding private keys to private key disabled wallets assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)); @@ -540,14 +542,14 @@ void LegacyScriptPubKeyMan::LoadKeyMetadata(const CKeyID &keyID, const CKeyMetadata &meta) { - AssertLockHeld(cs_wallet); + LOCK(cs_KeyStore); UpdateTimeFirstKey(meta.nCreateTime); mapKeyMetadata[keyID] = meta; } void LegacyScriptPubKeyMan::LoadScriptMetadata(const CScriptID &script_id, const CKeyMetadata &meta) { - AssertLockHeld(cs_wallet); + LOCK(cs_KeyStore); UpdateTimeFirstKey(meta.nCreateTime); m_script_metadata[script_id] = meta; } @@ -596,7 +598,7 @@ return false; } - LOCK(cs_wallet); + LOCK(cs_KeyStore); if (encrypted_batch) { return encrypted_batch->WriteCryptedKey( vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]); @@ -624,7 +626,6 @@ } bool LegacyScriptPubKeyMan::RemoveWatchOnly(const CScript &dest) { - AssertLockHeld(cs_wallet); { LOCK(cs_KeyStore); setWatchOnly.erase(dest); @@ -690,7 +691,7 @@ } void LegacyScriptPubKeyMan::SetHDChain(const CHDChain &chain, bool memonly) { - LOCK(cs_wallet); + LOCK(cs_KeyStore); if (!memonly && !WalletBatch(m_storage.GetDatabase()).WriteHDChain(chain)) { throw std::runtime_error(std::string(__func__) + ": writing chain failed"); @@ -727,7 +728,7 @@ KeyOriginInfo &info) const { CKeyMetadata meta; { - LOCK(cs_wallet); + LOCK(cs_KeyStore); auto it = mapKeyMetadata.find(keyID); if (it != mapKeyMetadata.end()) { meta = it->second; @@ -779,7 +780,7 @@ bool internal) { assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)); assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET)); - AssertLockHeld(cs_wallet); + AssertLockHeld(cs_KeyStore); // default to compressed public keys if we want 0.6.0 wallets bool fCompressed = m_storage.CanSupportFeature(FEATURE_COMPRPUBKEY); @@ -896,7 +897,7 @@ void LegacyScriptPubKeyMan::LoadKeyPool(int64_t nIndex, const CKeyPool &keypool) { - AssertLockHeld(cs_wallet); + LOCK(cs_KeyStore); if (keypool.m_pre_split) { set_pre_split_keypool.insert(nIndex); } else if (keypool.fInternal) { @@ -919,7 +920,7 @@ bool LegacyScriptPubKeyMan::CanGenerateKeys() { // A wallet can generate keys if it has an HD seed (IsHDEnabled) or it is a // non-HD wallet (pre FEATURE_HD) - LOCK(cs_wallet); + LOCK(cs_KeyStore); return IsHDEnabled() || !m_storage.CanSupportFeature(FEATURE_HD); } @@ -943,7 +944,7 @@ metadata.has_key_origin = false; metadata.hd_seed_id = seed.GetID(); - LOCK(cs_wallet); + LOCK(cs_KeyStore); // mem store the metadata mapKeyMetadata[seed.GetID()] = metadata; @@ -958,7 +959,7 @@ } void LegacyScriptPubKeyMan::SetHDSeed(const CPubKey &seed) { - LOCK(cs_wallet); + LOCK(cs_KeyStore); // Store the keyid (hash160) together with the child index counter in the // database as a hdchain object. @@ -980,7 +981,7 @@ if (m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { return false; } - LOCK(cs_wallet); + LOCK(cs_KeyStore); WalletBatch batch(m_storage.GetDatabase()); for (const int64_t nIndex : setInternalKeyPool) { @@ -1013,7 +1014,7 @@ return false; } { - LOCK(cs_wallet); + LOCK(cs_KeyStore); if (m_storage.IsLocked()) { return false; @@ -1066,7 +1067,7 @@ void LegacyScriptPubKeyMan::AddKeypoolPubkeyWithDB(const CPubKey &pubkey, const bool internal, WalletBatch &batch) { - LOCK(cs_wallet); + LOCK(cs_KeyStore); // How in the hell did you use so many keys? assert(m_max_keypool_index < std::numeric_limits::max()); int64_t index = ++m_max_keypool_index; @@ -1099,7 +1100,7 @@ const CTxDestination &) { // Return to key pool { - LOCK(cs_wallet); + LOCK(cs_KeyStore); if (fInternal) { setInternalKeyPool.insert(nIndex); } else if (!set_pre_split_keypool.empty()) { @@ -1124,7 +1125,7 @@ } CKeyPool keypool; - LOCK(cs_wallet); + LOCK(cs_KeyStore); int64_t nIndex; if (!ReserveKeyFromKeyPool(nIndex, keypool, internal) && !m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { @@ -1148,7 +1149,7 @@ nIndex = -1; keypool.vchPubKey = CPubKey(); { - LOCK(cs_wallet); + LOCK(cs_KeyStore); bool fReturningInternal = fRequestedInternal; fReturningInternal &= @@ -1207,7 +1208,7 @@ } void LegacyScriptPubKeyMan::MarkReserveKeysAsUsed(int64_t keypool_id) { - AssertLockHeld(cs_wallet); + AssertLockHeld(cs_KeyStore); bool internal = setInternalKeyPool.count(keypool_id); if (!internal) { assert(setExternalKeyPool.count(keypool_id) || @@ -1293,7 +1294,7 @@ bool LegacyScriptPubKeyMan::AddKeyOriginWithDB(WalletBatch &batch, const CPubKey &pubkey, const KeyOriginInfo &info) { - LOCK(cs_wallet); + LOCK(cs_KeyStore); std::copy(info.fingerprint, info.fingerprint + 4, mapKeyMetadata[pubkey.GetID()].key_origin.fingerprint); mapKeyMetadata[pubkey.GetID()].key_origin.path = info.path; @@ -1417,7 +1418,7 @@ // Temporary CWallet accessors and aliases. LegacyScriptPubKeyMan::LegacyScriptPubKeyMan(CWallet &wallet) - : ScriptPubKeyMan(wallet), m_wallet(wallet), cs_wallet(wallet.cs_wallet) {} + : ScriptPubKeyMan(wallet), m_wallet(wallet) {} void LegacyScriptPubKeyMan::NotifyWatchonlyChanged(bool fHaveWatchOnly) const { return m_wallet.NotifyWatchonlyChanged(fHaveWatchOnly); diff --git a/src/wallet/test/ismine_tests.cpp b/src/wallet/test/ismine_tests.cpp --- a/src/wallet/test/ismine_tests.cpp +++ b/src/wallet/test/ismine_tests.cpp @@ -39,7 +39,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); - LOCK(keystore.cs_wallet); + LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); scriptPubKey = GetScriptForRawPubKey(pubkeys[0]); // Keystore does not have key @@ -56,7 +56,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); - LOCK(keystore.cs_wallet); + LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey); // Keystore does not have key @@ -74,7 +74,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); - LOCK(keystore.cs_wallet); + LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0])); // Keystore does not have key @@ -91,7 +91,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); - LOCK(keystore.cs_wallet); + LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey)); // Keystore does not have key @@ -109,7 +109,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); - LOCK(keystore.cs_wallet); + LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0])); scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript)); @@ -134,7 +134,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); - LOCK(keystore.cs_wallet); + LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); CScript redeemscript_inner = GetScriptForDestination(PKHash(pubkeys[0])); @@ -157,7 +157,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); - LOCK(keystore.cs_wallet); + LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]}); @@ -191,7 +191,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); - LOCK(keystore.cs_wallet); + LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); BOOST_CHECK( keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey)); BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1])); @@ -215,7 +215,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); - LOCK(keystore.cs_wallet); + LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0])); scriptPubKey.clear(); @@ -229,7 +229,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); - LOCK(keystore.cs_wallet); + LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0])); scriptPubKey.clear(); diff --git a/src/wallet/test/psbt_wallet_tests.cpp b/src/wallet/test/psbt_wallet_tests.cpp --- a/src/wallet/test/psbt_wallet_tests.cpp +++ b/src/wallet/test/psbt_wallet_tests.cpp @@ -18,7 +18,7 @@ BOOST_AUTO_TEST_CASE(psbt_updater_test) { auto spk_man = m_wallet.GetLegacyScriptPubKeyMan(); - LOCK(m_wallet.cs_wallet); + LOCK2(m_wallet.cs_wallet, spk_man->cs_KeyStore); // Create prevtxs and add to wallet CDataStream s_prev_tx1( diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -30,8 +30,7 @@ static void AddKey(CWallet &wallet, const CKey &key) { auto spk_man = wallet.GetLegacyScriptPubKeyMan(); - LOCK(wallet.cs_wallet); - AssertLockHeld(spk_man->cs_wallet); + LOCK2(wallet.cs_wallet, spk_man->cs_KeyStore); spk_man->AddKeyPubKey(key, key.GetPubKey()); } @@ -248,8 +247,7 @@ std::make_shared(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); auto spk_man = wallet->GetLegacyScriptPubKeyMan(); - LOCK(wallet->cs_wallet); - AssertLockHeld(spk_man->cs_wallet); + LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore); spk_man->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME; spk_man->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); @@ -303,8 +301,7 @@ auto locked_chain = chain->lock(); LockAssertion lock(::cs_main); - LOCK(wallet.cs_wallet); - AssertLockHeld(spk_man->cs_wallet); + LOCK2(wallet.cs_wallet, spk_man->cs_KeyStore); wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash()); @@ -413,7 +410,7 @@ CScript p2pk = GetScriptForRawPubKey(add_pubkey); CKeyID add_address = add_pubkey.GetID(); CPubKey found_pubkey; - LOCK(spk_man->cs_wallet); + LOCK(spk_man->cs_KeyStore); // all Scripts (i.e. also all PubKeys) are added to the general watch-only // set @@ -433,7 +430,6 @@ BOOST_CHECK(found_pubkey == CPubKey()); } - AssertLockHeld(spk_man->cs_wallet); spk_man->RemoveWatchOnly(p2pk); BOOST_CHECK(!spk_man->HaveWatchOnly(p2pk)); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -671,7 +671,7 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notifications { private: - CKeyingMaterial vMasterKey GUARDED_BY(cs_KeyStore); + CKeyingMaterial vMasterKey GUARDED_BY(cs_wallet); bool Unlock(const CKeyingMaterial &vMasterKeyIn, bool accept_no_keys = false); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -252,6 +252,7 @@ // Set a seed for the wallet { + LOCK(wallet->cs_wallet); if (auto spk_man = wallet->m_spk_man.get()) { if (!spk_man->SetupGeneration()) { error = Untranslated("Unable to generate initial keys"); @@ -299,7 +300,6 @@ } if (m_spk_man) { - AssertLockHeld(m_spk_man->cs_wallet); m_spk_man->UpgradeKeyMetadata(); } SetWalletFlag(WALLET_FLAG_KEY_ORIGIN_METADATA); @@ -1423,6 +1423,7 @@ } bool CWallet::CanGetAddresses(bool internal) { + LOCK(cs_wallet); { auto spk_man = m_spk_man.get(); if (spk_man && spk_man->CanGetAddresses(internal)) { @@ -1532,7 +1533,7 @@ if (!spk_man) { return false; } - AssertLockHeld(spk_man->cs_wallet); + LOCK(spk_man->cs_KeyStore); return spk_man->ImportScripts(scripts, timestamp); } @@ -1542,7 +1543,7 @@ if (!spk_man) { return false; } - AssertLockHeld(spk_man->cs_wallet); + LOCK(spk_man->cs_KeyStore); return spk_man->ImportPrivKeys(privkey_map, timestamp); } @@ -1555,7 +1556,7 @@ if (!spk_man) { return false; } - AssertLockHeld(spk_man->cs_wallet); + LOCK(spk_man->cs_KeyStore); return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool, internal, timestamp); } @@ -1569,7 +1570,7 @@ if (!spk_man) { return false; } - AssertLockHeld(spk_man->cs_wallet); + LOCK(spk_man->cs_KeyStore); if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) { return false; @@ -3493,7 +3494,6 @@ unsigned int count = 0; if (auto spk_man = m_spk_man.get()) { - AssertLockHeld(spk_man->cs_wallet); count += spk_man->KeypoolCountExternalKeys(); } @@ -3511,6 +3511,7 @@ } bool CWallet::TopUpKeyPool(unsigned int kpSize) { + LOCK(cs_wallet); bool res = true; if (auto spk_man = m_spk_man.get()) { res &= spk_man->TopUp(kpSize); @@ -3538,6 +3539,7 @@ bool CWallet::GetNewChangeDestination(const OutputType type, CTxDestination &dest, std::string &error) { + LOCK(cs_wallet); error.clear(); ReserveDestination reservedest(this, type); @@ -3551,6 +3553,7 @@ } int64_t CWallet::GetOldestKeyPoolTime() { + LOCK(cs_wallet); int64_t oldestKey = std::numeric_limits::max(); if (auto spk_man = m_spk_man.get()) { oldestKey = spk_man->GetOldestKeyPoolTime(); @@ -3822,7 +3825,7 @@ LegacyScriptPubKeyMan *spk_man = GetLegacyScriptPubKeyMan(); assert(spk_man != nullptr); - AssertLockHeld(spk_man->cs_wallet); + LOCK(spk_man->cs_KeyStore); // Get birth times for keys with metadata. for (const auto &entry : spk_man->mapKeyMetadata) { @@ -4189,6 +4192,7 @@ walletInstance->SetWalletFlags(wallet_creation_flags, false); if (!(wallet_creation_flags & (WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET))) { + LOCK(walletInstance->cs_wallet); if (auto spk_man = walletInstance->m_spk_man.get()) { if (!spk_man->SetupGeneration()) { error = _("Unable to generate initial keys"); @@ -4604,7 +4608,7 @@ if (!IsCrypted()) { return false; } - LOCK(cs_KeyStore); + LOCK(cs_wallet); return vMasterKey.empty(); } @@ -4614,7 +4618,7 @@ } { - LOCK(cs_KeyStore); + LOCK(cs_wallet); vMasterKey.clear(); } @@ -4624,7 +4628,7 @@ bool CWallet::Unlock(const CKeyingMaterial &vMasterKeyIn, bool accept_no_keys) { { - LOCK(cs_KeyStore); + LOCK(cs_wallet); if (m_spk_man) { if (!m_spk_man->CheckDecryptionKey(vMasterKeyIn, accept_no_keys)) { return false; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -209,8 +209,7 @@ static bool ReadKeyValue(CWallet *pwallet, CDataStream &ssKey, CDataStream &ssValue, CWalletScanState &wss, std::string &strType, std::string &strErr) - EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet, - pwallet->GetLegacyScriptPubKeyMan()->cs_wallet) { + EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) { try { // Unserialize // Taking advantage of the fact that pair serialization is just the two @@ -464,7 +463,6 @@ DBErrors result = DBErrors::LOAD_OK; LOCK(pwallet->cs_wallet); - AssertLockHeld(pwallet->GetLegacyScriptPubKeyMan()->cs_wallet); try { int nMinVersion = 0; if (m_batch.Read(DBKeys::MINVERSION, nMinVersion)) { @@ -557,6 +555,7 @@ if ((wss.nKeys + wss.nCKeys + wss.nWatchKeys) != wss.nKeyMeta) { auto spk_man = pwallet->GetLegacyScriptPubKeyMan(); if (spk_man) { + LOCK(spk_man->cs_KeyStore); spk_man->UpdateTimeFirstKey(1); } } @@ -766,7 +765,6 @@ { // Required in LoadKeyMetadata(): LOCK(dummyWallet->cs_wallet); - AssertLockHeld(dummyWallet->GetLegacyScriptPubKeyMan()->cs_wallet); fReadOK = ReadKeyValue(dummyWallet, ssKey, ssValue, dummyWss, strType, strErr); } diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp --- a/src/wallet/wallettool.cpp +++ b/src/wallet/wallettool.cpp @@ -33,6 +33,7 @@ new CWallet(Params(), nullptr /* chain */, WalletLocation(name), WalletDatabase::Create(path)), WalletToolReleaseWallet); + LOCK(wallet_instance->cs_wallet); bool first_run = true; DBErrors load_wallet_ret = wallet_instance->LoadWallet(first_run); if (load_wallet_ret != DBErrors::LOAD_OK) {