diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp --- a/src/bench/coin_selection.cpp +++ b/src/bench/coin_selection.cpp @@ -36,8 +36,9 @@ NodeContext node; auto chain = interfaces::MakeChain(node, Params()); - const CWallet wallet(Params(), chain.get(), WalletLocation(), - WalletDatabase::CreateDummy()); + CWallet wallet(Params(), chain.get(), WalletLocation(), + WalletDatabase::CreateDummy()); + wallet.SetupLegacyScriptPubKeyMan(); std::vector> wtxs; LOCK(wallet.cs_wallet); @@ -109,12 +110,13 @@ NodeContext node; auto chain = interfaces::MakeChain(node, Params()); - const CWallet wallet(Params(), chain.get(), WalletLocation(), - WalletDatabase::CreateDummy()); + CWallet wallet(Params(), chain.get(), WalletLocation(), + WalletDatabase::CreateDummy()); LOCK(wallet.cs_wallet); // Setup + wallet.SetupLegacyScriptPubKeyMan(); std::vector utxo_pool; CoinSet selection; Amount value_ret = Amount::zero(); diff --git a/src/bench/wallet_balance.cpp b/src/bench/wallet_balance.cpp --- a/src/bench/wallet_balance.cpp +++ b/src/bench/wallet_balance.cpp @@ -24,6 +24,7 @@ CWallet wallet{config.GetChainParams(), chain.get(), WalletLocation(), WalletDatabase::CreateMock()}; { + wallet.SetupLegacyScriptPubKeyMan(); bool first_run; if (wallet.LoadWallet(first_run) != DBErrors::LOAD_OK) { assert(false); diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp --- a/src/qt/test/addressbooktests.cpp +++ b/src/qt/test/addressbooktests.cpp @@ -60,6 +60,7 @@ std::shared_ptr wallet = std::make_shared( Params(), node.context()->chain.get(), WalletLocation(), WalletDatabase::CreateMock()); + wallet->SetupLegacyScriptPubKeyMan(); bool firstRun; wallet->LoadWallet(firstRun); 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 @@ -120,7 +120,7 @@ bool firstRun; wallet->LoadWallet(firstRun); { - auto spk_man = wallet->GetLegacyScriptPubKeyMan(); + auto spk_man = wallet->GetOrCreateLegacyScriptPubKeyMan(); auto locked_chain = wallet->chain().lock(); LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore); wallet->SetAddressBook( diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -143,7 +143,7 @@ "private keys disabled"); } - EnsureLegacyScriptPubKeyMan(*wallet); + EnsureLegacyScriptPubKeyMan(*wallet, true); WalletRescanReserver reserver(*pwallet); bool fRescan = true; @@ -290,7 +290,7 @@ } .Check(request); - EnsureLegacyScriptPubKeyMan(*pwallet); + EnsureLegacyScriptPubKeyMan(*pwallet, true); std::string strLabel; if (!request.params[1].isNull()) { @@ -543,7 +543,7 @@ } .Check(request); - EnsureLegacyScriptPubKeyMan(*wallet); + EnsureLegacyScriptPubKeyMan(*wallet, true); std::string strLabel; if (!request.params[1].isNull()) { @@ -639,7 +639,7 @@ } .Check(request); - EnsureLegacyScriptPubKeyMan(*wallet); + EnsureLegacyScriptPubKeyMan(*wallet, true); if (pwallet->chain().havePruned()) { // Exit early and print an error. @@ -1689,7 +1689,7 @@ RPCTypeCheck(mainRequest.params, {UniValue::VARR, UniValue::VOBJ}); - EnsureLegacyScriptPubKeyMan(*wallet); + EnsureLegacyScriptPubKeyMan(*wallet, true); const UniValue &requests = mainRequest.params[0]; diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h --- a/src/wallet/rpcwallet.h +++ b/src/wallet/rpcwallet.h @@ -47,7 +47,8 @@ std::string HelpRequiringPassphrase(const CWallet *); void EnsureWalletIsUnlocked(const CWallet *); bool EnsureWalletIsAvailable(const CWallet *, bool avoidException); -LegacyScriptPubKeyMan &EnsureLegacyScriptPubKeyMan(CWallet &wallet); +LegacyScriptPubKeyMan &EnsureLegacyScriptPubKeyMan(CWallet &wallet, + bool also_create = false); UniValue signrawtransactionwithwallet(const Config &config, const JSONRPCRequest &request); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -144,8 +144,14 @@ } } -LegacyScriptPubKeyMan &EnsureLegacyScriptPubKeyMan(CWallet &wallet) { +// also_create should only be set to true only when the RPC is expected to add +// things to a blank wallet and make it no longer blank +LegacyScriptPubKeyMan &EnsureLegacyScriptPubKeyMan(CWallet &wallet, + bool also_create) { LegacyScriptPubKeyMan *spk_man = wallet.GetLegacyScriptPubKeyMan(); + if (!spk_man && also_create) { + spk_man = wallet.GetOrCreateLegacyScriptPubKeyMan(); + } if (!spk_man) { throw JSONRPCError(RPC_WALLET_ERROR, "This type of wallet does not support this command"); @@ -4498,7 +4504,8 @@ } .Check(request); - LegacyScriptPubKeyMan &spk_man = EnsureLegacyScriptPubKeyMan(*pwallet); + LegacyScriptPubKeyMan &spk_man = + EnsureLegacyScriptPubKeyMan(*pwallet, true); if (pwallet->chain().isInitialBlockDownload()) { throw JSONRPCError( diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp --- a/src/wallet/test/coinselector_tests.cpp +++ b/src/wallet/test/coinselector_tests.cpp @@ -141,6 +141,7 @@ // Branch and bound coin selection tests BOOST_AUTO_TEST_CASE(bnb_search_test) { LOCK(m_wallet.cs_wallet); + m_wallet.SetupLegacyScriptPubKeyMan(); // Setup std::vector utxo_pool; @@ -313,6 +314,7 @@ bool bnb_used; LOCK(testWallet.cs_wallet); + testWallet.SetupLegacyScriptPubKeyMan(); // test multiple times to allow for differences in the shuffle order for (int i = 0; i < RUN_TESTS; i++) { @@ -712,6 +714,7 @@ bool bnb_used; LOCK(m_wallet.cs_wallet); + m_wallet.SetupLegacyScriptPubKeyMan(); empty_wallet(); @@ -736,6 +739,7 @@ auto testChain = interfaces::MakeChain(testNode, Params()); CWallet testWallet(Params(), testChain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + testWallet.SetupLegacyScriptPubKeyMan(); // Random generator stuff std::default_random_engine generator; 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,6 +39,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); scriptPubKey = GetScriptForRawPubKey(pubkeys[0]); @@ -56,6 +57,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey); @@ -74,6 +76,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0])); @@ -91,6 +94,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey)); @@ -109,6 +113,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0])); @@ -134,6 +139,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); CScript redeemscript_inner = @@ -157,6 +163,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); scriptPubKey = @@ -191,6 +198,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); BOOST_CHECK( keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey)); @@ -215,6 +223,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0])); @@ -229,6 +238,7 @@ { CWallet keystore(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0])); 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 @@ -17,7 +17,7 @@ BOOST_FIXTURE_TEST_SUITE(psbt_wallet_tests, WalletTestingSetup) BOOST_AUTO_TEST_CASE(psbt_updater_test) { - auto spk_man = m_wallet.GetLegacyScriptPubKeyMan(); + auto spk_man = m_wallet.GetOrCreateLegacyScriptPubKeyMan(); LOCK2(m_wallet.cs_wallet, spk_man->cs_KeyStore); // Create prevtxs and add to wallet 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 @@ -29,7 +29,7 @@ BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup) static void AddKey(CWallet &wallet, const CKey &key) { - auto spk_man = wallet.GetLegacyScriptPubKeyMan(); + auto spk_man = wallet.GetOrCreateLegacyScriptPubKeyMan(); LOCK2(wallet.cs_wallet, spk_man->cs_KeyStore); spk_man->AddKeyPubKey(key, key.GetPubKey()); } @@ -164,6 +164,7 @@ std::shared_ptr wallet = std::make_shared(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + wallet->SetupLegacyScriptPubKeyMan(); AddWallet(wallet); UniValue keys; keys.setArray(); @@ -246,7 +247,7 @@ std::shared_ptr wallet = std::make_shared(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); - auto spk_man = wallet->GetLegacyScriptPubKeyMan(); + auto spk_man = wallet->GetOrCreateLegacyScriptPubKeyMan(); LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore); spk_man->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME; @@ -266,6 +267,7 @@ std::shared_ptr wallet = std::make_shared(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + wallet->SetupLegacyScriptPubKeyMan(); JSONRPCRequest request; request.params.setArray(); @@ -296,7 +298,7 @@ auto chain = interfaces::MakeChain(node, Params()); CWallet wallet(Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); - auto spk_man = wallet.GetLegacyScriptPubKeyMan(); + auto spk_man = wallet.GetOrCreateLegacyScriptPubKeyMan(); CWalletTx wtx(&wallet, m_coinbase_txns.back()); auto locked_chain = chain->lock(); @@ -453,7 +455,8 @@ BOOST_AUTO_TEST_CASE(WatchOnlyPubKeys) { CKey key; CPubKey pubkey; - LegacyScriptPubKeyMan *spk_man = m_wallet.GetLegacyScriptPubKeyMan(); + LegacyScriptPubKeyMan *spk_man = + m_wallet.GetOrCreateLegacyScriptPubKeyMan(); BOOST_CHECK(!spk_man->HaveWatchOnly()); @@ -627,6 +630,7 @@ auto chain = interfaces::MakeChain(node, Params()); std::shared_ptr wallet = std::make_shared( Params(), chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + wallet->SetupLegacyScriptPubKeyMan(); wallet->SetMinVersion(FEATURE_LATEST); wallet->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS); BOOST_CHECK(!wallet->TopUpKeyPool(1000)); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1412,25 +1412,18 @@ SignatureData &sigdata) const; LegacyScriptPubKeyMan *GetLegacyScriptPubKeyMan() const; + LegacyScriptPubKeyMan *GetOrCreateLegacyScriptPubKeyMan(); + + //! Make a LegacyScriptPubKeyMan and set it for all types, internal, and + //! external. + void SetupLegacyScriptPubKeyMan(); const CKeyingMaterial &GetEncryptionKey() const override; bool HasEncryptionKeys() const override; // Temporary LegacyScriptPubKeyMan accessors and aliases. friend class LegacyScriptPubKeyMan; - std::unique_ptr m_spk_man = - std::make_unique(*this); - RecursiveMutex &cs_KeyStore = m_spk_man->cs_KeyStore; - LegacyScriptPubKeyMan::KeyMap & - mapKeys GUARDED_BY(cs_KeyStore) = m_spk_man->mapKeys; - LegacyScriptPubKeyMan::ScriptMap & - mapScripts GUARDED_BY(cs_KeyStore) = m_spk_man->mapScripts; - LegacyScriptPubKeyMan::CryptedKeyMap & - mapCryptedKeys GUARDED_BY(cs_KeyStore) = m_spk_man->mapCryptedKeys; - LegacyScriptPubKeyMan::WatchOnlySet & - setWatchOnly GUARDED_BY(cs_KeyStore) = m_spk_man->setWatchOnly; - LegacyScriptPubKeyMan::WatchKeyMap & - mapWatchKeys GUARDED_BY(cs_KeyStore) = m_spk_man->mapWatchKeys; + std::unique_ptr m_spk_man; /** Get last block processed height */ int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3360,12 +3360,10 @@ } } + // This wallet is in its first run if there are no ScriptPubKeyMans and it + // isn't blank or no privkeys { - LOCK(cs_KeyStore); - // This wallet is in its first run if all of these are empty - fFirstRunRet = mapKeys.empty() && mapCryptedKeys.empty() && - mapWatchKeys.empty() && setWatchOnly.empty() && - mapScripts.empty() && + fFirstRunRet = !m_spk_man && !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET); } @@ -4190,6 +4188,10 @@ walletInstance->SetMinVersion(FEATURE_LATEST); walletInstance->SetWalletFlags(wallet_creation_flags, false); + + // Always create LegacyScriptPubKeyMan for now + walletInstance->SetupLegacyScriptPubKeyMan(); + if (!(wallet_creation_flags & (WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET))) { LOCK(walletInstance->cs_wallet); @@ -4659,6 +4661,17 @@ return m_spk_man.get(); } +LegacyScriptPubKeyMan *CWallet::GetOrCreateLegacyScriptPubKeyMan() { + SetupLegacyScriptPubKeyMan(); + return GetLegacyScriptPubKeyMan(); +} + +void CWallet::SetupLegacyScriptPubKeyMan() { + if (!m_spk_man) { + m_spk_man = std::make_unique(*this); + } +} + const CKeyingMaterial &CWallet::GetEncryptionKey() const { return vMasterKey; } diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -273,7 +273,8 @@ char fYes; ssValue >> fYes; if (fYes == '1') { - pwallet->GetLegacyScriptPubKeyMan()->LoadWatchOnly(script); + pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadWatchOnly( + script); } } else if (strType == DBKeys::KEY) { CPubKey vchPubKey; @@ -322,7 +323,8 @@ strErr = "Error reading wallet database: CPrivKey corrupt"; return false; } - if (!pwallet->GetLegacyScriptPubKeyMan()->LoadKey(key, vchPubKey)) { + if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadKey( + key, vchPubKey)) { strErr = "Error reading wallet database: " "LegacyScriptPubKeyMan::LoadKey failed"; return false; @@ -355,7 +357,7 @@ ssValue >> vchPrivKey; wss.nCKeys++; - if (!pwallet->GetLegacyScriptPubKeyMan()->LoadCryptedKey( + if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadCryptedKey( vchPubKey, vchPrivKey)) { strErr = "Error reading wallet database: " "LegacyScriptPubKeyMan::LoadCryptedKey failed"; @@ -368,7 +370,7 @@ CKeyMetadata keyMeta; ssValue >> keyMeta; wss.nKeyMeta++; - pwallet->GetLegacyScriptPubKeyMan()->LoadKeyMetadata( + pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadKeyMetadata( vchPubKey.GetID(), keyMeta); } else if (strType == DBKeys::WATCHMETA) { CScript script; @@ -376,7 +378,7 @@ CKeyMetadata keyMeta; ssValue >> keyMeta; wss.nKeyMeta++; - pwallet->GetLegacyScriptPubKeyMan()->LoadScriptMetadata( + pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadScriptMetadata( CScriptID(script), keyMeta); } else if (strType == DBKeys::DEFAULTKEY) { // We don't want or need the default key, but if there is one set, @@ -394,13 +396,15 @@ CKeyPool keypool; ssValue >> keypool; - pwallet->GetLegacyScriptPubKeyMan()->LoadKeyPool(nIndex, keypool); + pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadKeyPool(nIndex, + keypool); } else if (strType == DBKeys::CSCRIPT) { uint160 hash; ssKey >> hash; CScript script; ssValue >> script; - if (!pwallet->GetLegacyScriptPubKeyMan()->LoadCScript(script)) { + if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadCScript( + script)) { strErr = "Error reading wallet database: " "LegacyScriptPubKeyMan::LoadCScript failed"; return false; @@ -418,7 +422,8 @@ } else if (strType == DBKeys::HDCHAIN) { CHDChain chain; ssValue >> chain; - pwallet->GetLegacyScriptPubKeyMan()->SetHDChain(chain, true); + pwallet->GetOrCreateLegacyScriptPubKeyMan()->SetHDChain(chain, + true); } else if (strType == DBKeys::FLAGS) { uint64_t flags; ssValue >> flags; @@ -553,7 +558,7 @@ // nTimeFirstKey is only reliable if all keys have metadata if ((wss.nKeys + wss.nCKeys + wss.nWatchKeys) != wss.nKeyMeta) { - auto spk_man = pwallet->GetLegacyScriptPubKeyMan(); + auto spk_man = pwallet->GetOrCreateLegacyScriptPubKeyMan(); if (spk_man) { LOCK(spk_man->cs_KeyStore); spk_man->UpdateTimeFirstKey(1); diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp --- a/src/wallet/wallettool.cpp +++ b/src/wallet/wallettool.cpp @@ -44,7 +44,7 @@ wallet_instance->SetMinVersion(FEATURE_HD_SPLIT); // generate a new HD seed - auto spk_man = wallet_instance->GetLegacyScriptPubKeyMan(); + auto spk_man = wallet_instance->GetOrCreateLegacyScriptPubKeyMan(); CPubKey seed = spk_man->GenerateNewSeed(); spk_man->SetHDSeed(seed);