diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp --- a/src/interfaces/node.cpp +++ b/src/interfaces/node.cpp @@ -244,8 +244,8 @@ std::vector> getWallets() override { #ifdef ENABLE_WALLET std::vector> wallets; - for (CWallet *wallet : GetWallets()) { - wallets.emplace_back(MakeWallet(*wallet)); + for (const std::shared_ptr &wallet : GetWallets()) { + wallets.emplace_back(MakeWallet(wallet)); } return wallets; #else @@ -268,7 +268,9 @@ } std::unique_ptr handleLoadWallet(LoadWalletFn fn) override { CHECK_WALLET(return MakeHandler(::uiInterface.LoadWallet.connect( - [fn](CWallet *wallet) { fn(MakeWallet(*wallet)); }))); + [fn](std::shared_ptr wallet) { + fn(MakeWallet(wallet)); + }))); } std::unique_ptr handleNotifyNumConnectionsChanged( NotifyNumConnectionsChangedFn fn) override { diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h --- a/src/interfaces/wallet.h +++ b/src/interfaces/wallet.h @@ -345,7 +345,7 @@ //! Return implementation of Wallet interface. This function will be undefined //! in builds where ENABLE_WALLET is false. -std::unique_ptr MakeWallet(CWallet &wallet); +std::unique_ptr MakeWallet(const std::shared_ptr &wallet); } // namespace interfaces diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -117,7 +117,8 @@ class WalletImpl : public Wallet { public: - WalletImpl(CWallet &wallet) : m_wallet(wallet) {} + WalletImpl(const std::shared_ptr &wallet) + : m_shared_wallet(wallet), m_wallet(*wallet.get()) {} bool encryptWallet(const SecureString &wallet_passphrase) override { return m_wallet.EncryptWallet(wallet_passphrase); @@ -431,12 +432,13 @@ return GetMinimumFee(m_wallet, tx_bytes, coin_control, g_mempool); } + std::shared_ptr m_shared_wallet; CWallet &m_wallet; }; } // namespace -std::unique_ptr MakeWallet(CWallet &wallet) { +std::unique_ptr MakeWallet(const std::shared_ptr &wallet) { return std::make_unique(wallet); } 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 @@ -56,15 +56,16 @@ */ void TestAddAddressesToSendBook() { TestChain100Setup test; - CWallet wallet(Params(), "mock", WalletDatabase::CreateMock()); + std::shared_ptr wallet = std::make_shared( + Params(), "mock", WalletDatabase::CreateMock()); bool firstRun; - wallet.LoadWallet(firstRun); + wallet->LoadWallet(firstRun); auto build_address = [&wallet]() { CKey key; key.MakeNewKey(true); CTxDestination dest(GetDestinationForKey( - key.GetPubKey(), wallet.m_default_address_type)); + key.GetPubKey(), wallet->m_default_address_type)); return std::make_pair( dest, QString::fromStdString(EncodeCashAddr(dest, Params()))); @@ -88,13 +89,14 @@ std::tie(std::ignore, new_address) = build_address(); { - LOCK(wallet.cs_wallet); - wallet.SetAddressBook(r_key_dest, r_label.toStdString(), "receive"); - wallet.SetAddressBook(s_key_dest, s_label.toStdString(), "send"); + LOCK(wallet->cs_wallet); + wallet->SetAddressBook(r_key_dest, r_label.toStdString(), "receive"); + wallet->SetAddressBook(s_key_dest, s_label.toStdString(), "send"); } auto check_addbook_size = [&wallet](int expected_size) { - QCOMPARE(static_cast(wallet.mapAddressBook.size()), expected_size); + QCOMPARE(static_cast(wallet->mapAddressBook.size()), + expected_size); }; // We should start with the two addresses we added earlier and nothing else. @@ -105,10 +107,10 @@ PlatformStyle::instantiate("other")); auto node = interfaces::MakeNode(); OptionsModel optionsModel(*node); - AddWallet(&wallet); + AddWallet(wallet); WalletModel walletModel(std::move(node->getWallets()[0]), *node, platformStyle.get(), &optionsModel); - RemoveWallet(&wallet); + RemoveWallet(wallet); EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress); editAddressDialog.setModel(walletModel.getAddressTableModel()); 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 @@ -107,45 +107,46 @@ test.CreateAndProcessBlock( {}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey())); } - CWallet wallet(Params(), "mock", WalletDatabase::CreateMock()); + std::shared_ptr wallet = std::make_shared( + Params(), "mock", WalletDatabase::CreateMock()); bool firstRun; - wallet.LoadWallet(firstRun); + wallet->LoadWallet(firstRun); { - LOCK(wallet.cs_wallet); - wallet.SetAddressBook( + LOCK(wallet->cs_wallet); + wallet->SetAddressBook( GetDestinationForKey(test.coinbaseKey.GetPubKey(), - wallet.m_default_address_type), + wallet->m_default_address_type), "", "receive"); - wallet.AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey()); + wallet->AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey()); } { LOCK(cs_main); - WalletRescanReserver reserver(&wallet); + WalletRescanReserver reserver(wallet.get()); reserver.reserve(); - wallet.ScanForWalletTransactions(chainActive.Genesis(), nullptr, - reserver, true); + wallet->ScanForWalletTransactions(chainActive.Genesis(), nullptr, + reserver, true); } - wallet.SetBroadcastTransactions(true); + wallet->SetBroadcastTransactions(true); // Create widgets for sending coins and listing transactions. std::unique_ptr platformStyle( PlatformStyle::instantiate("other")); auto node = interfaces::MakeNode(); OptionsModel optionsModel(*node); - AddWallet(&wallet); + AddWallet(wallet); WalletModel walletModel(std::move(node->getWallets().back()), *node, platformStyle.get(), &optionsModel); - RemoveWallet(&wallet); + RemoveWallet(wallet); // Send two transactions, and verify they are added to transaction list. SendCoinsDialog sendCoinsDialog(platformStyle.get(), &walletModel); TransactionTableModel *transactionTableModel = walletModel.getTransactionTableModel(); QCOMPARE(transactionTableModel->rowCount({}), 105); - uint256 txid1 = - SendCoins(wallet, sendCoinsDialog, CTxDestination(CKeyID()), 5 * COIN); - uint256 txid2 = - SendCoins(wallet, sendCoinsDialog, CTxDestination(CKeyID()), 10 * COIN); + uint256 txid1 = SendCoins(*wallet.get(), sendCoinsDialog, + CTxDestination(CKeyID()), 5 * COIN); + uint256 txid2 = SendCoins(*wallet.get(), sendCoinsDialog, + CTxDestination(CKeyID()), 10 * COIN); QCOMPARE(transactionTableModel->rowCount({}), 107); QVERIFY(FindTx(*transactionTableModel, txid1).isValid()); QVERIFY(FindTx(*transactionTableModel, txid2).isValid()); diff --git a/src/ui_interface.h b/src/ui_interface.h --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -7,6 +7,7 @@ #define BITCOIN_UI_INTERFACE_H #include +#include #include #include @@ -107,7 +108,7 @@ boost::signals2::signal NotifyAlertChanged; /** A wallet has been loaded. */ - boost::signals2::signal LoadWallet; + boost::signals2::signal wallet)> LoadWallet; /** * Show progress e.g. for verifychain. diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -349,7 +349,7 @@ } for (const std::string &walletFile : gArgs.GetArgs("-wallet")) { - CWallet *const pwallet = CWallet::CreateWalletFromFile( + std::shared_ptr pwallet = CWallet::CreateWalletFromFile( chainParams, walletFile, fs::absolute(walletFile, GetWalletDir())); if (!pwallet) { return false; @@ -361,7 +361,7 @@ } void WalletInit::Start(CScheduler &scheduler) const { - for (CWallet *pwallet : GetWallets()) { + for (const std::shared_ptr &pwallet : GetWallets()) { pwallet->postInitProcess(); } @@ -375,20 +375,19 @@ } void WalletInit::Flush() const { - for (CWallet *pwallet : GetWallets()) { + for (const std::shared_ptr &pwallet : GetWallets()) { pwallet->Flush(false); } } void WalletInit::Stop() const { - for (CWallet *pwallet : GetWallets()) { + for (const std::shared_ptr &pwallet : GetWallets()) { pwallet->Flush(true); } } void WalletInit::Close() const { - for (CWallet *pwallet : GetWallets()) { + for (const std::shared_ptr &pwallet : GetWallets()) { RemoveWallet(pwallet); - delete pwallet; } } diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -108,7 +108,8 @@ } UniValue importprivkey(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -214,7 +215,8 @@ } UniValue abortrescan(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -283,7 +285,8 @@ } UniValue importaddress(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -385,7 +388,8 @@ UniValue importprunedfunds(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -464,7 +468,8 @@ UniValue removeprunedfunds(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -510,7 +515,8 @@ } UniValue importpubkey(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -596,7 +602,8 @@ } UniValue importwallet(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -753,7 +760,8 @@ } UniValue dumpprivkey(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -798,7 +806,8 @@ } UniValue dumpwallet(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -1323,7 +1332,9 @@ } UniValue importmulti(const Config &config, const JSONRPCRequest &mainRequest) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(mainRequest); + std::shared_ptr const wallet = + GetWalletForJSONRPCRequest(mainRequest); + CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, mainRequest.fHelp)) { return NullUniValue; } diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h --- a/src/wallet/rpcwallet.h +++ b/src/wallet/rpcwallet.h @@ -22,7 +22,8 @@ * @param[in] request JSONRPCRequest that wishes to access a wallet * @return NULL if no wallet should be used, or a pointer to the CWallet */ -CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest &); +std::shared_ptr +GetWalletForJSONRPCRequest(const JSONRPCRequest &request); std::string HelpRequiringPassphrase(CWallet *); void EnsureWalletIsUnlocked(CWallet *); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -50,13 +50,14 @@ return res; } -CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest &request) { +std::shared_ptr +GetWalletForJSONRPCRequest(const JSONRPCRequest &request) { if (request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) { // wallet endpoint was used std::string requestedWallet = urlDecode(request.URI.substr(WALLET_ENDPOINT_BASE.size())); - CWallet *pwallet = GetWallet(requestedWallet); + std::shared_ptr pwallet = GetWallet(requestedWallet); if (!pwallet) { throw JSONRPCError( RPC_WALLET_NOT_FOUND, @@ -65,7 +66,7 @@ return pwallet; } - std::vector wallets = GetWallets(); + std::vector> wallets = GetWallets(); return wallets.size() == 1 || (request.fHelp && wallets.size() > 0) ? wallets[0] : nullptr; @@ -149,7 +150,9 @@ static UniValue getnewaddress(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -226,7 +229,9 @@ static UniValue getlabeladdress(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -263,7 +268,9 @@ static UniValue getrawchangeaddress(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -315,7 +322,9 @@ } static UniValue setlabel(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -373,7 +382,9 @@ static UniValue getaccount(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -416,7 +427,9 @@ static UniValue getaddressesbyaccount(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -515,7 +528,9 @@ static UniValue sendtoaddress(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -608,7 +623,9 @@ static UniValue listaddressgroupings(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -670,7 +687,9 @@ static UniValue signmessage(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -743,7 +762,9 @@ static UniValue getreceivedbyaddress(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -829,7 +850,9 @@ static UniValue getreceivedbylabel(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -905,7 +928,9 @@ static UniValue getbalance(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -994,7 +1019,9 @@ static UniValue getunconfirmedbalance(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -1015,7 +1042,9 @@ } static UniValue movecmd(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -1083,7 +1112,9 @@ } static UniValue sendfrom(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -1195,7 +1226,9 @@ } static UniValue sendmany(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -1382,7 +1415,9 @@ static UniValue addmultisigaddress(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -1642,7 +1677,9 @@ static UniValue listreceivedbyaddress(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -1706,7 +1743,9 @@ static UniValue listreceivedbylabel(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -1872,7 +1911,9 @@ static UniValue listtransactions(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -2065,7 +2106,9 @@ static UniValue listaccounts(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -2167,7 +2210,9 @@ static UniValue listsinceblock(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -2375,7 +2420,9 @@ static UniValue gettransaction(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -2512,7 +2559,9 @@ static UniValue abandontransaction(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -2564,7 +2613,9 @@ static UniValue backupwallet(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -2597,7 +2648,9 @@ static UniValue keypoolrefill(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -2647,7 +2700,9 @@ static UniValue walletpassphrase(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -2735,7 +2790,9 @@ static UniValue walletpassphrasechange(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -2796,7 +2853,9 @@ static UniValue walletlock(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -2841,7 +2900,9 @@ static UniValue encryptwallet(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -2919,7 +2980,9 @@ static UniValue lockunspent(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -3077,7 +3140,9 @@ static UniValue listlockunspent(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -3136,7 +3201,9 @@ } static UniValue settxfee(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -3169,7 +3236,9 @@ static UniValue getwalletinfo(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -3275,13 +3344,13 @@ UniValue obj(UniValue::VARR); - for (CWallet *pwallet : GetWallets()) { - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + for (const std::shared_ptr &wallet : GetWallets()) { + if (!EnsureWalletIsAvailable(wallet.get(), request.fHelp)) { return NullUniValue; } - LOCK(pwallet->cs_wallet); - obj.push_back(pwallet->GetName()); + LOCK(wallet->cs_wallet); + obj.push_back(wallet->GetName()); } return obj; @@ -3328,7 +3397,7 @@ "Wallet file verification failed: " + error); } - CWallet *const wallet = CWallet::CreateWalletFromFile( + std::shared_ptr const wallet = CWallet::CreateWalletFromFile( chainParams, wallet_file, fs::absolute(wallet_file, GetWalletDir())); if (!wallet) { throw JSONRPCError(RPC_WALLET_ERROR, "Wallet loading failed."); @@ -3346,7 +3415,9 @@ static UniValue resendwallettransactions(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -3389,7 +3460,9 @@ static UniValue listunspent(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -3607,7 +3680,9 @@ static UniValue fundrawtransaction(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -3822,7 +3897,9 @@ UniValue signrawtransactionwithwallet(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -3915,7 +3992,8 @@ } static UniValue generate(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; @@ -3965,7 +4043,9 @@ } UniValue rescanblockchain(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } @@ -4160,7 +4240,9 @@ } UniValue getaddressinfo(const Config &config, const JSONRPCRequest &request) { - CWallet *const pwallet = GetWalletForJSONRPCRequest(request); + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet *const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } 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 @@ -73,8 +73,9 @@ // before the missing block, and success for a key whose creation time is // after. { - CWallet wallet(Params(), "dummy", WalletDatabase::CreateDummy()); - AddWallet(&wallet); + std::shared_ptr wallet = std::make_shared( + Params(), "dummy", WalletDatabase::CreateDummy()); + AddWallet(wallet); UniValue keys; keys.setArray(); UniValue key; @@ -113,7 +114,7 @@ "rescanning the relevant blocks (see -reindex and " "-rescan options).\"}},{\"success\":true}]", 0, oldTip->GetBlockTimeMax(), TIMESTAMP_WINDOW)); - RemoveWallet(&wallet); + RemoveWallet(wallet); } } @@ -151,37 +152,39 @@ // Import key into wallet and call dumpwallet to create backup file. { - CWallet wallet(Params(), "dummy", WalletDatabase::CreateDummy()); - LOCK(wallet.cs_wallet); - wallet.mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = + std::shared_ptr wallet = std::make_shared( + Params(), "dummy", WalletDatabase::CreateDummy()); + LOCK(wallet->cs_wallet); + wallet->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME; - wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); + wallet->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); JSONRPCRequest request; request.params.setArray(); request.params.push_back(backup_file); - AddWallet(&wallet); + AddWallet(wallet); ::dumpwallet(GetConfig(), request); - RemoveWallet(&wallet); + RemoveWallet(wallet); } // Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME // were scanned, and no prior blocks were scanned. { - CWallet wallet(Params(), "dummy", WalletDatabase::CreateDummy()); + std::shared_ptr wallet = std::make_shared( + Params(), "dummy", WalletDatabase::CreateDummy()); JSONRPCRequest request; request.params.setArray(); request.params.push_back(backup_file); - AddWallet(&wallet); + AddWallet(wallet); ::importwallet(GetConfig(), request); - RemoveWallet(&wallet); + RemoveWallet(wallet); - LOCK(wallet.cs_wallet); - BOOST_CHECK_EQUAL(wallet.mapWallet.size(), 3U); + LOCK(wallet->cs_wallet); + BOOST_CHECK_EQUAL(wallet->mapWallet.size(), 3U); BOOST_CHECK_EQUAL(m_coinbase_txns.size(), 103U); for (size_t i = 0; i < m_coinbase_txns.size(); ++i) { - bool found = wallet.GetWalletTx(m_coinbase_txns[i]->GetId()); + bool found = wallet->GetWalletTx(m_coinbase_txns[i]->GetId()); bool expected = i >= 100; BOOST_CHECK_EQUAL(found, expected); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -31,11 +31,11 @@ #include #include -bool AddWallet(CWallet *wallet); -bool RemoveWallet(CWallet *wallet); +bool AddWallet(const std::shared_ptr &wallet); +bool RemoveWallet(const std::shared_ptr &wallet); bool HasWallets(); -std::vector GetWallets(); -CWallet *GetWallet(const std::string &name); +std::vector> GetWallets(); +std::shared_ptr GetWallet(const std::string &name); //! Default for -keypool static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000; @@ -1239,9 +1239,9 @@ * Initializes the wallet, returns a new CWallet instance or a null pointer * in case of an error. */ - static CWallet *CreateWalletFromFile(const CChainParams &chainParams, - const std::string &name, - const fs::path &path); + static std::shared_ptr + CreateWalletFromFile(const CChainParams &chainParams, + const std::string &name, const fs::path &path); /** * Wallet post-init setup diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -42,12 +42,12 @@ #include static CCriticalSection cs_wallets; -static std::vector vpwallets GUARDED_BY(cs_wallets); +static std::vector> vpwallets GUARDED_BY(cs_wallets); -bool AddWallet(CWallet *wallet) { +bool AddWallet(const std::shared_ptr &wallet) { LOCK(cs_wallets); assert(wallet); - std::vector::const_iterator i = + std::vector>::const_iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet); if (i != vpwallets.end()) { return false; @@ -56,10 +56,10 @@ return true; } -bool RemoveWallet(CWallet *wallet) { +bool RemoveWallet(const std::shared_ptr &wallet) { LOCK(cs_wallets); assert(wallet); - std::vector::iterator i = + std::vector>::iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet); if (i == vpwallets.end()) { return false; @@ -73,14 +73,14 @@ return !vpwallets.empty(); } -std::vector GetWallets() { +std::vector> GetWallets() { LOCK(cs_wallets); return vpwallets; } -CWallet *GetWallet(const std::string &name) { +std::shared_ptr GetWallet(const std::string &name) { LOCK(cs_wallets); - for (CWallet *wallet : vpwallets) { + for (const std::shared_ptr &wallet : vpwallets) { if (wallet->GetName() == name) { return wallet; } @@ -3427,8 +3427,6 @@ return nLoadWalletRet; } - uiInterface.LoadWallet(this); - return DBErrors::LOAD_OK; } @@ -4306,9 +4304,9 @@ error_string); } -CWallet *CWallet::CreateWalletFromFile(const CChainParams &chainParams, - const std::string &name, - const fs::path &path) { +std::shared_ptr +CWallet::CreateWalletFromFile(const CChainParams &chainParams, + const std::string &name, const fs::path &path) { const std::string &walletFile = name; // Needed to restore wallet transaction meta data after -zapwallettxes @@ -4331,11 +4329,8 @@ int64_t nStart = GetTimeMillis(); bool fFirstRun = true; - // Make a temporary wallet unique pointer so memory doesn't get leaked if - // wallet creation fails. - auto temp_wallet = std::make_unique(chainParams, name, - WalletDatabase::Create(path)); - CWallet *walletInstance = temp_wallet.get(); + std::shared_ptr walletInstance = std::make_shared( + chainParams, name, WalletDatabase::Create(path)); DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun); if (nLoadWalletRet != DBErrors::LOAD_OK) { if (nLoadWalletRet == DBErrors::CORRUPT) { @@ -4366,6 +4361,8 @@ } } + uiInterface.LoadWallet(walletInstance); + if (gArgs.GetBoolArg("-upgradewallet", fFirstRun)) { int nMaxVersion = gArgs.GetArg("-upgradewallet", 0); // The -upgradewallet without argument case @@ -4541,7 +4538,7 @@ nStart = GetTimeMillis(); { - WalletRescanReserver reserver(walletInstance); + WalletRescanReserver reserver(walletInstance.get()); if (!reserver.reserve()) { InitError( _("Failed to rescan the wallet during initialization")); @@ -4581,7 +4578,7 @@ // Register with the validation interface. It's ok to do this after rescan // since we're still holding cs_main. - RegisterValidationInterface(temp_wallet.release()); + RegisterValidationInterface(walletInstance.get()); walletInstance->SetBroadcastTransactions( gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST)); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -762,7 +762,7 @@ return; } - for (CWallet *pwallet : GetWallets()) { + for (const std::shared_ptr &pwallet : GetWallets()) { WalletDatabase &dbh = pwallet->GetDBHandle(); unsigned int nUpdateCounter = dbh.nUpdateCounter;