Merge #13063: Use shared pointer to retain wallet instance

80b4910f7d wallet: Use shared pointer to retain wallet instance (João Barbosa)

Pull request description:

  Currently there are 3 places where it makes sense to retain a wallet shared pointer:
   - `vpwallets`;
   - `interfaces::Wallet` interface instance - used by the UI;
   - wallet RPC functions - given by `GetWalletForJSONRPCRequest`.

  The way it is now it is possible to have, for instance, listunspent RPC and in parallel unload the wallet (once #13111 is merged) without blocking. Once the RPC finishes, the shared pointer will release the wallet.

  It is also possible to get all existing wallets without blocking because the caller keeps a local list of shared pointers.

  This is mostly relevant for wallet unloading.

  This PR replaces #11402.

Tree-SHA512: b7e37c7e1ab56626085afe2d40b1628e8d4f0dbda08df01b7e618ecd2d894ce9b83d4219443f444ba889096286eff002f163cb0a48f37063b62e9ba4ccfa6cce
This commit is contained in:
Wladimir J. van der Laan 2018-05-24 11:29:07 +02:00
commit 6378eef18f
No known key found for this signature in database
GPG Key ID: 1E4AED62986CD25D
15 changed files with 239 additions and 139 deletions

View File

@ -222,8 +222,8 @@ class NodeImpl : public Node
{ {
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
std::vector<std::unique_ptr<Wallet>> wallets; std::vector<std::unique_ptr<Wallet>> wallets;
for (CWallet* wallet : GetWallets()) { for (const std::shared_ptr<CWallet>& wallet : GetWallets()) {
wallets.emplace_back(MakeWallet(*wallet)); wallets.emplace_back(MakeWallet(wallet));
} }
return wallets; return wallets;
#else #else
@ -249,7 +249,7 @@ class NodeImpl : public Node
std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) override std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) override
{ {
CHECK_WALLET( CHECK_WALLET(
return MakeHandler(::uiInterface.LoadWallet.connect([fn](CWallet* wallet) { fn(MakeWallet(*wallet)); }))); return MakeHandler(::uiInterface.LoadWallet.connect([fn](std::shared_ptr<CWallet> wallet) { fn(MakeWallet(wallet)); })));
} }
std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override
{ {

View File

@ -118,7 +118,7 @@ WalletTxOut MakeWalletTxOut(CWallet& wallet, const CWalletTx& wtx, int n, int de
class WalletImpl : public Wallet class WalletImpl : public Wallet
{ {
public: public:
WalletImpl(CWallet& wallet) : m_wallet(wallet) {} WalletImpl(const std::shared_ptr<CWallet>& wallet) : m_shared_wallet(wallet), m_wallet(*wallet.get()) {}
bool encryptWallet(const SecureString& wallet_passphrase) override bool encryptWallet(const SecureString& wallet_passphrase) override
{ {
@ -453,11 +453,12 @@ public:
return MakeHandler(m_wallet.NotifyWatchonlyChanged.connect(fn)); return MakeHandler(m_wallet.NotifyWatchonlyChanged.connect(fn));
} }
std::shared_ptr<CWallet> m_shared_wallet;
CWallet& m_wallet; CWallet& m_wallet;
}; };
} // namespace } // namespace
std::unique_ptr<Wallet> MakeWallet(CWallet& wallet) { return MakeUnique<WalletImpl>(wallet); } std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet) { return MakeUnique<WalletImpl>(wallet); }
} // namespace interfaces } // namespace interfaces

View File

@ -363,7 +363,7 @@ struct WalletTxOut
//! Return implementation of Wallet interface. This function will be undefined //! Return implementation of Wallet interface. This function will be undefined
//! in builds where ENABLE_WALLET is false. //! in builds where ENABLE_WALLET is false.
std::unique_ptr<Wallet> MakeWallet(CWallet& wallet); std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet);
} // namespace interfaces } // namespace interfaces

View File

@ -56,15 +56,15 @@ void EditAddressAndSubmit(
void TestAddAddressesToSendBook() void TestAddAddressesToSendBook()
{ {
TestChain100Setup test; TestChain100Setup test;
CWallet wallet("mock", WalletDatabase::CreateMock()); std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("mock", WalletDatabase::CreateMock());
bool firstRun; bool firstRun;
wallet.LoadWallet(firstRun); wallet->LoadWallet(firstRun);
auto build_address = [&wallet]() { auto build_address = [&wallet]() {
CKey key; CKey key;
key.MakeNewKey(true); key.MakeNewKey(true);
CTxDestination dest(GetDestinationForKey( CTxDestination dest(GetDestinationForKey(
key.GetPubKey(), wallet.m_default_address_type)); key.GetPubKey(), wallet->m_default_address_type));
return std::make_pair(dest, QString::fromStdString(EncodeDestination(dest))); return std::make_pair(dest, QString::fromStdString(EncodeDestination(dest)));
}; };
@ -87,13 +87,13 @@ void TestAddAddressesToSendBook()
std::tie(std::ignore, new_address) = build_address(); std::tie(std::ignore, new_address) = build_address();
{ {
LOCK(wallet.cs_wallet); LOCK(wallet->cs_wallet);
wallet.SetAddressBook(r_key_dest, r_label.toStdString(), "receive"); wallet->SetAddressBook(r_key_dest, r_label.toStdString(), "receive");
wallet.SetAddressBook(s_key_dest, s_label.toStdString(), "send"); wallet->SetAddressBook(s_key_dest, s_label.toStdString(), "send");
} }
auto check_addbook_size = [&wallet](int expected_size) { auto check_addbook_size = [&wallet](int expected_size) {
QCOMPARE(static_cast<int>(wallet.mapAddressBook.size()), expected_size); QCOMPARE(static_cast<int>(wallet->mapAddressBook.size()), expected_size);
}; };
// We should start with the two addresses we added earlier and nothing else. // We should start with the two addresses we added earlier and nothing else.
@ -103,9 +103,9 @@ void TestAddAddressesToSendBook()
std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other")); std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
auto node = interfaces::MakeNode(); auto node = interfaces::MakeNode();
OptionsModel optionsModel(*node); OptionsModel optionsModel(*node);
AddWallet(&wallet); AddWallet(wallet);
WalletModel walletModel(std::move(node->getWallets()[0]), *node, platformStyle.get(), &optionsModel); WalletModel walletModel(std::move(node->getWallets()[0]), *node, platformStyle.get(), &optionsModel);
RemoveWallet(&wallet); RemoveWallet(wallet);
EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress); EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress);
editAddressDialog.setModel(walletModel.getAddressTableModel()); editAddressDialog.setModel(walletModel.getAddressTableModel());

View File

@ -144,21 +144,21 @@ void TestGUI()
for (int i = 0; i < 5; ++i) { for (int i = 0; i < 5; ++i) {
test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey())); test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey()));
} }
CWallet wallet("mock", WalletDatabase::CreateMock()); std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("mock", WalletDatabase::CreateMock());
bool firstRun; bool firstRun;
wallet.LoadWallet(firstRun); wallet->LoadWallet(firstRun);
{ {
LOCK(wallet.cs_wallet); LOCK(wallet->cs_wallet);
wallet.SetAddressBook(GetDestinationForKey(test.coinbaseKey.GetPubKey(), wallet.m_default_address_type), "", "receive"); wallet->SetAddressBook(GetDestinationForKey(test.coinbaseKey.GetPubKey(), wallet->m_default_address_type), "", "receive");
wallet.AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey()); wallet->AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey());
} }
{ {
LOCK(cs_main); LOCK(cs_main);
WalletRescanReserver reserver(&wallet); WalletRescanReserver reserver(wallet.get());
reserver.reserve(); 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. // Create widgets for sending coins and listing transactions.
std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other")); std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
@ -166,17 +166,17 @@ void TestGUI()
TransactionView transactionView(platformStyle.get()); TransactionView transactionView(platformStyle.get());
auto node = interfaces::MakeNode(); auto node = interfaces::MakeNode();
OptionsModel optionsModel(*node); OptionsModel optionsModel(*node);
AddWallet(&wallet); AddWallet(wallet);
WalletModel walletModel(std::move(node->getWallets().back()), *node, platformStyle.get(), &optionsModel); WalletModel walletModel(std::move(node->getWallets().back()), *node, platformStyle.get(), &optionsModel);
RemoveWallet(&wallet); RemoveWallet(wallet);
sendCoinsDialog.setModel(&walletModel); sendCoinsDialog.setModel(&walletModel);
transactionView.setModel(&walletModel); transactionView.setModel(&walletModel);
// Send two transactions, and verify they are added to transaction list. // Send two transactions, and verify they are added to transaction list.
TransactionTableModel* transactionTableModel = walletModel.getTransactionTableModel(); TransactionTableModel* transactionTableModel = walletModel.getTransactionTableModel();
QCOMPARE(transactionTableModel->rowCount({}), 105); QCOMPARE(transactionTableModel->rowCount({}), 105);
uint256 txid1 = SendCoins(wallet, sendCoinsDialog, CKeyID(), 5 * COIN, false /* rbf */); uint256 txid1 = SendCoins(*wallet.get(), sendCoinsDialog, CKeyID(), 5 * COIN, false /* rbf */);
uint256 txid2 = SendCoins(wallet, sendCoinsDialog, CKeyID(), 10 * COIN, true /* rbf */); uint256 txid2 = SendCoins(*wallet.get(), sendCoinsDialog, CKeyID(), 10 * COIN, true /* rbf */);
QCOMPARE(transactionTableModel->rowCount({}), 107); QCOMPARE(transactionTableModel->rowCount({}), 107);
QVERIFY(FindTx(*transactionTableModel, txid1).isValid()); QVERIFY(FindTx(*transactionTableModel, txid1).isValid());
QVERIFY(FindTx(*transactionTableModel, txid2).isValid()); QVERIFY(FindTx(*transactionTableModel, txid2).isValid());

View File

@ -988,7 +988,8 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
UniValue signrawtransaction(const JSONRPCRequest& request) UniValue signrawtransaction(const JSONRPCRequest& request)
{ {
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
#endif #endif
if (request.fHelp || request.params.size() < 1 || request.params.size() > 4) if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)

View File

@ -6,6 +6,7 @@
#ifndef BITCOIN_UI_INTERFACE_H #ifndef BITCOIN_UI_INTERFACE_H
#define BITCOIN_UI_INTERFACE_H #define BITCOIN_UI_INTERFACE_H
#include <memory>
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
@ -92,7 +93,7 @@ public:
boost::signals2::signal<void ()> NotifyAlertChanged; boost::signals2::signal<void ()> NotifyAlertChanged;
/** A wallet has been loaded. */ /** A wallet has been loaded. */
boost::signals2::signal<void (CWallet* wallet)> LoadWallet; boost::signals2::signal<void (std::shared_ptr<CWallet> wallet)> LoadWallet;
/** /**
* Show progress e.g. for verifychain. * Show progress e.g. for verifychain.

View File

@ -226,7 +226,7 @@ bool WalletInit::Open() const
} }
for (const std::string& walletFile : gArgs.GetArgs("-wallet")) { for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
CWallet * const pwallet = CWallet::CreateWalletFromFile(walletFile, fs::absolute(walletFile, GetWalletDir())); std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(walletFile, fs::absolute(walletFile, GetWalletDir()));
if (!pwallet) { if (!pwallet) {
return false; return false;
} }
@ -238,7 +238,7 @@ bool WalletInit::Open() const
void WalletInit::Start(CScheduler& scheduler) const void WalletInit::Start(CScheduler& scheduler) const
{ {
for (CWallet* pwallet : GetWallets()) { for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
pwallet->postInitProcess(); pwallet->postInitProcess();
} }
@ -248,22 +248,21 @@ void WalletInit::Start(CScheduler& scheduler) const
void WalletInit::Flush() const void WalletInit::Flush() const
{ {
for (CWallet* pwallet : GetWallets()) { for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
pwallet->Flush(false); pwallet->Flush(false);
} }
} }
void WalletInit::Stop() const void WalletInit::Stop() const
{ {
for (CWallet* pwallet : GetWallets()) { for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
pwallet->Flush(true); pwallet->Flush(true);
} }
} }
void WalletInit::Close() const void WalletInit::Close() const
{ {
for (CWallet* pwallet : GetWallets()) { for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
RemoveWallet(pwallet); RemoveWallet(pwallet);
delete pwallet;
} }
} }

View File

@ -56,7 +56,7 @@ static std::string DecodeDumpString(const std::string &str) {
for (unsigned int pos = 0; pos < str.length(); pos++) { for (unsigned int pos = 0; pos < str.length(); pos++) {
unsigned char c = str[pos]; unsigned char c = str[pos];
if (c == '%' && pos+2 < str.length()) { if (c == '%' && pos+2 < str.length()) {
c = (((str[pos+1]>>6)*9+((str[pos+1]-'0')&15)) << 4) | c = (((str[pos+1]>>6)*9+((str[pos+1]-'0')&15)) << 4) |
((str[pos+2]>>6)*9+((str[pos+2]-'0')&15)); ((str[pos+2]>>6)*9+((str[pos+2]-'0')&15));
pos += 2; pos += 2;
} }
@ -89,7 +89,8 @@ static bool GetWalletAddressesForKey(CWallet * const pwallet, const CKeyID &keyi
UniValue importprivkey(const JSONRPCRequest& request) UniValue importprivkey(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -185,7 +186,8 @@ UniValue importprivkey(const JSONRPCRequest& request)
UniValue abortrescan(const JSONRPCRequest& request) UniValue abortrescan(const JSONRPCRequest& request)
{ {
CWallet* const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -246,7 +248,8 @@ static void ImportAddress(CWallet* const pwallet, const CTxDestination& dest, co
UniValue importaddress(const JSONRPCRequest& request) UniValue importaddress(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -330,7 +333,8 @@ UniValue importaddress(const JSONRPCRequest& request)
UniValue importprunedfunds(const JSONRPCRequest& request) UniValue importprunedfunds(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -392,7 +396,8 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
UniValue removeprunedfunds(const JSONRPCRequest& request) UniValue removeprunedfunds(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -430,7 +435,8 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
UniValue importpubkey(const JSONRPCRequest& request) UniValue importpubkey(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -506,7 +512,8 @@ UniValue importpubkey(const JSONRPCRequest& request)
UniValue importwallet(const JSONRPCRequest& request) UniValue importwallet(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -640,7 +647,8 @@ UniValue importwallet(const JSONRPCRequest& request)
UniValue dumpprivkey(const JSONRPCRequest& request) UniValue dumpprivkey(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -683,7 +691,8 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
UniValue dumpwallet(const JSONRPCRequest& request) UniValue dumpwallet(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -1127,7 +1136,8 @@ static int64_t GetImportTimestamp(const UniValue& data, int64_t now)
UniValue importmulti(const JSONRPCRequest& mainRequest) UniValue importmulti(const JSONRPCRequest& mainRequest)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(mainRequest); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(mainRequest);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, mainRequest.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, mainRequest.fHelp)) {
return NullUniValue; return NullUniValue;
} }

View File

@ -40,17 +40,17 @@
static const std::string WALLET_ENDPOINT_BASE = "/wallet/"; static const std::string WALLET_ENDPOINT_BASE = "/wallet/";
CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request) std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
{ {
if (request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) { if (request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) {
// wallet endpoint was used // wallet endpoint was used
std::string requestedWallet = urlDecode(request.URI.substr(WALLET_ENDPOINT_BASE.size())); std::string requestedWallet = urlDecode(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
CWallet* pwallet = GetWallet(requestedWallet); std::shared_ptr<CWallet> pwallet = GetWallet(requestedWallet);
if (!pwallet) throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded"); if (!pwallet) throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
return pwallet; return pwallet;
} }
std::vector<CWallet*> wallets = GetWallets(); std::vector<std::shared_ptr<CWallet>> wallets = GetWallets();
return wallets.size() == 1 || (request.fHelp && wallets.size() > 0) ? wallets[0] : nullptr; return wallets.size() == 1 || (request.fHelp && wallets.size() > 0) ? wallets[0] : nullptr;
} }
@ -134,7 +134,9 @@ static std::string LabelFromValue(const UniValue& value)
static UniValue getnewaddress(const JSONRPCRequest& request) static UniValue getnewaddress(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -198,7 +200,9 @@ CTxDestination GetLabelDestination(CWallet* const pwallet, const std::string& la
static UniValue getlabeladdress(const JSONRPCRequest& request) static UniValue getlabeladdress(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -256,7 +260,9 @@ static UniValue getlabeladdress(const JSONRPCRequest& request)
static UniValue getrawchangeaddress(const JSONRPCRequest& request) static UniValue getrawchangeaddress(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -304,7 +310,9 @@ static UniValue getrawchangeaddress(const JSONRPCRequest& request)
static UniValue setlabel(const JSONRPCRequest& request) static UniValue setlabel(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -358,7 +366,9 @@ static UniValue setlabel(const JSONRPCRequest& request)
static UniValue getaccount(const JSONRPCRequest& request) static UniValue getaccount(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -401,7 +411,9 @@ static UniValue getaccount(const JSONRPCRequest& request)
static UniValue getaddressesbyaccount(const JSONRPCRequest& request) static UniValue getaddressesbyaccount(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -487,7 +499,9 @@ static CTransactionRef SendMoney(CWallet * const pwallet, const CTxDestination &
static UniValue sendtoaddress(const JSONRPCRequest& request) static UniValue sendtoaddress(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -574,7 +588,9 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
static UniValue listaddressgroupings(const JSONRPCRequest& request) static UniValue listaddressgroupings(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -631,7 +647,9 @@ static UniValue listaddressgroupings(const JSONRPCRequest& request)
static UniValue signmessage(const JSONRPCRequest& request) static UniValue signmessage(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -692,7 +710,9 @@ static UniValue signmessage(const JSONRPCRequest& request)
static UniValue getreceivedbyaddress(const JSONRPCRequest& request) static UniValue getreceivedbyaddress(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -757,7 +777,9 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request)
static UniValue getreceivedbylabel(const JSONRPCRequest& request) static UniValue getreceivedbylabel(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -827,7 +849,9 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request)
static UniValue getbalance(const JSONRPCRequest& request) static UniValue getbalance(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -910,7 +934,9 @@ static UniValue getbalance(const JSONRPCRequest& request)
static UniValue getunconfirmedbalance(const JSONRPCRequest &request) static UniValue getunconfirmedbalance(const JSONRPCRequest &request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -932,7 +958,9 @@ static UniValue getunconfirmedbalance(const JSONRPCRequest &request)
static UniValue movecmd(const JSONRPCRequest& request) static UniValue movecmd(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -989,7 +1017,9 @@ static UniValue movecmd(const JSONRPCRequest& request)
static UniValue sendfrom(const JSONRPCRequest& request) static UniValue sendfrom(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -1062,7 +1092,9 @@ static UniValue sendfrom(const JSONRPCRequest& request)
static UniValue sendmany(const JSONRPCRequest& request) static UniValue sendmany(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -1257,7 +1289,9 @@ static UniValue sendmany(const JSONRPCRequest& request)
static UniValue addmultisigaddress(const JSONRPCRequest& request) static UniValue addmultisigaddress(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -1392,7 +1426,9 @@ public:
static UniValue addwitnessaddress(const JSONRPCRequest& request) static UniValue addwitnessaddress(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -1624,7 +1660,9 @@ static UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bo
static UniValue listreceivedbyaddress(const JSONRPCRequest& request) static UniValue listreceivedbyaddress(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -1673,7 +1711,9 @@ static UniValue listreceivedbyaddress(const JSONRPCRequest& request)
static UniValue listreceivedbylabel(const JSONRPCRequest& request) static UniValue listreceivedbylabel(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -1838,7 +1878,9 @@ static void AcentryToJSON(const CAccountingEntry& acentry, const std::string& st
UniValue listtransactions(const JSONRPCRequest& request) UniValue listtransactions(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -2026,7 +2068,9 @@ UniValue listtransactions(const JSONRPCRequest& request)
static UniValue listaccounts(const JSONRPCRequest& request) static UniValue listaccounts(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -2119,7 +2163,9 @@ static UniValue listaccounts(const JSONRPCRequest& request)
static UniValue listsinceblock(const JSONRPCRequest& request) static UniValue listsinceblock(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -2258,7 +2304,9 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
static UniValue gettransaction(const JSONRPCRequest& request) static UniValue gettransaction(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -2352,7 +2400,9 @@ static UniValue gettransaction(const JSONRPCRequest& request)
static UniValue abandontransaction(const JSONRPCRequest& request) static UniValue abandontransaction(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -2396,7 +2446,9 @@ static UniValue abandontransaction(const JSONRPCRequest& request)
static UniValue backupwallet(const JSONRPCRequest& request) static UniValue backupwallet(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -2429,7 +2481,9 @@ static UniValue backupwallet(const JSONRPCRequest& request)
static UniValue keypoolrefill(const JSONRPCRequest& request) static UniValue keypoolrefill(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -2476,7 +2530,9 @@ static void LockWallet(CWallet* pWallet)
static UniValue walletpassphrase(const JSONRPCRequest& request) static UniValue walletpassphrase(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -2549,7 +2605,9 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
static UniValue walletpassphrasechange(const JSONRPCRequest& request) static UniValue walletpassphrasechange(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -2598,7 +2656,9 @@ static UniValue walletpassphrasechange(const JSONRPCRequest& request)
static UniValue walletlock(const JSONRPCRequest& request) static UniValue walletlock(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -2636,7 +2696,9 @@ static UniValue walletlock(const JSONRPCRequest& request)
static UniValue encryptwallet(const JSONRPCRequest& request) static UniValue encryptwallet(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -2696,7 +2758,9 @@ static UniValue encryptwallet(const JSONRPCRequest& request)
static UniValue lockunspent(const JSONRPCRequest& request) static UniValue lockunspent(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -2823,7 +2887,9 @@ static UniValue lockunspent(const JSONRPCRequest& request)
static UniValue listlockunspent(const JSONRPCRequest& request) static UniValue listlockunspent(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -2874,7 +2940,9 @@ static UniValue listlockunspent(const JSONRPCRequest& request)
static UniValue settxfee(const JSONRPCRequest& request) static UniValue settxfee(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -2903,7 +2971,9 @@ static UniValue settxfee(const JSONRPCRequest& request)
static UniValue getwalletinfo(const JSONRPCRequest& request) static UniValue getwalletinfo(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -2984,14 +3054,14 @@ static UniValue listwallets(const JSONRPCRequest& request)
UniValue obj(UniValue::VARR); UniValue obj(UniValue::VARR);
for (CWallet* pwallet : GetWallets()) { for (const std::shared_ptr<CWallet>& wallet : GetWallets()) {
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(wallet.get(), request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
LOCK(pwallet->cs_wallet); LOCK(wallet->cs_wallet);
obj.push_back(pwallet->GetName()); obj.push_back(wallet->GetName());
} }
return obj; return obj;
@ -3029,7 +3099,7 @@ UniValue loadwallet(const JSONRPCRequest& request)
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet file verification failed: " + error); throw JSONRPCError(RPC_WALLET_ERROR, "Wallet file verification failed: " + error);
} }
CWallet * const wallet = CWallet::CreateWalletFromFile(wallet_file, fs::absolute(wallet_file, GetWalletDir())); std::shared_ptr<CWallet> const wallet = CWallet::CreateWalletFromFile(wallet_file, fs::absolute(wallet_file, GetWalletDir()));
if (!wallet) { if (!wallet) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet loading failed."); throw JSONRPCError(RPC_WALLET_ERROR, "Wallet loading failed.");
} }
@ -3046,7 +3116,9 @@ UniValue loadwallet(const JSONRPCRequest& request)
static UniValue resendwallettransactions(const JSONRPCRequest& request) static UniValue resendwallettransactions(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -3081,7 +3153,9 @@ static UniValue resendwallettransactions(const JSONRPCRequest& request)
static UniValue listunspent(const JSONRPCRequest& request) static UniValue listunspent(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -3252,7 +3326,9 @@ static UniValue listunspent(const JSONRPCRequest& request)
static UniValue fundrawtransaction(const JSONRPCRequest& request) static UniValue fundrawtransaction(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -3452,7 +3528,9 @@ static UniValue fundrawtransaction(const JSONRPCRequest& request)
UniValue signrawtransactionwithwallet(const JSONRPCRequest& request) UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -3521,7 +3599,9 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
static UniValue bumpfee(const JSONRPCRequest& request) static UniValue bumpfee(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
return NullUniValue; return NullUniValue;
@ -3670,7 +3750,9 @@ static UniValue bumpfee(const JSONRPCRequest& request)
UniValue generate(const JSONRPCRequest& request) UniValue generate(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
@ -3715,7 +3797,9 @@ UniValue generate(const JSONRPCRequest& request)
UniValue rescanblockchain(const JSONRPCRequest& request) UniValue rescanblockchain(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -3920,7 +4004,9 @@ static UniValue AddressBookDataToJSON(const CAddressBookData& data, const bool v
UniValue getaddressinfo(const JSONRPCRequest& request) UniValue getaddressinfo(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -4038,7 +4124,9 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
static UniValue getaddressesbylabel(const JSONRPCRequest& request) static UniValue getaddressesbylabel(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -4081,7 +4169,9 @@ static UniValue getaddressesbylabel(const JSONRPCRequest& request)
static UniValue listlabels(const JSONRPCRequest& request) static UniValue listlabels(const JSONRPCRequest& request)
{ {
CWallet * const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }
@ -4133,7 +4223,8 @@ static UniValue listlabels(const JSONRPCRequest& request)
UniValue sethdseed(const JSONRPCRequest& request) UniValue sethdseed(const JSONRPCRequest& request)
{ {
CWallet* const pwallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;

View File

@ -20,7 +20,7 @@ void RegisterWalletRPCCommands(CRPCTable &t);
* @param[in] request JSONRPCRequest that wishes to access a wallet * @param[in] request JSONRPCRequest that wishes to access a wallet
* @return nullptr if no wallet should be used, or a pointer to the CWallet * @return nullptr if no wallet should be used, or a pointer to the CWallet
*/ */
CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request); std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request);
std::string HelpRequiringPassphrase(CWallet *); std::string HelpRequiringPassphrase(CWallet *);
void EnsureWalletIsUnlocked(CWallet *); void EnsureWalletIsUnlocked(CWallet *);

View File

@ -73,8 +73,8 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
// before the missing block, and success for a key whose creation time is // before the missing block, and success for a key whose creation time is
// after. // after.
{ {
CWallet wallet("dummy", WalletDatabase::CreateDummy()); std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("dummy", WalletDatabase::CreateDummy());
AddWallet(&wallet); AddWallet(wallet);
UniValue keys; UniValue keys;
keys.setArray(); keys.setArray();
UniValue key; UniValue key;
@ -105,7 +105,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
"downloading and rescanning the relevant blocks (see -reindex and -rescan " "downloading and rescanning the relevant blocks (see -reindex and -rescan "
"options).\"}},{\"success\":true}]", "options).\"}},{\"success\":true}]",
0, oldTip->GetBlockTimeMax(), TIMESTAMP_WINDOW)); 0, oldTip->GetBlockTimeMax(), TIMESTAMP_WINDOW));
RemoveWallet(&wallet); RemoveWallet(wallet);
} }
} }
@ -132,36 +132,36 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// Import key into wallet and call dumpwallet to create backup file. // Import key into wallet and call dumpwallet to create backup file.
{ {
CWallet wallet("dummy", WalletDatabase::CreateDummy()); std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("dummy", WalletDatabase::CreateDummy());
LOCK(wallet.cs_wallet); LOCK(wallet->cs_wallet);
wallet.mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME; wallet->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME;
wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); wallet->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
JSONRPCRequest request; JSONRPCRequest request;
request.params.setArray(); request.params.setArray();
request.params.push_back((pathTemp / "wallet.backup").string()); request.params.push_back((pathTemp / "wallet.backup").string());
AddWallet(&wallet); AddWallet(wallet);
::dumpwallet(request); ::dumpwallet(request);
RemoveWallet(&wallet); RemoveWallet(wallet);
} }
// Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME // Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME
// were scanned, and no prior blocks were scanned. // were scanned, and no prior blocks were scanned.
{ {
CWallet wallet("dummy", WalletDatabase::CreateDummy()); std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("dummy", WalletDatabase::CreateDummy());
JSONRPCRequest request; JSONRPCRequest request;
request.params.setArray(); request.params.setArray();
request.params.push_back((pathTemp / "wallet.backup").string()); request.params.push_back((pathTemp / "wallet.backup").string());
AddWallet(&wallet); AddWallet(wallet);
::importwallet(request); ::importwallet(request);
RemoveWallet(&wallet); RemoveWallet(wallet);
LOCK(wallet.cs_wallet); LOCK(wallet->cs_wallet);
BOOST_CHECK_EQUAL(wallet.mapWallet.size(), 3U); BOOST_CHECK_EQUAL(wallet->mapWallet.size(), 3U);
BOOST_CHECK_EQUAL(m_coinbase_txns.size(), 103U); BOOST_CHECK_EQUAL(m_coinbase_txns.size(), 103U);
for (size_t i = 0; i < m_coinbase_txns.size(); ++i) { for (size_t i = 0; i < m_coinbase_txns.size(); ++i) {
bool found = wallet.GetWalletTx(m_coinbase_txns[i]->GetHash()); bool found = wallet->GetWalletTx(m_coinbase_txns[i]->GetHash());
bool expected = i >= 100; bool expected = i >= 100;
BOOST_CHECK_EQUAL(found, expected); BOOST_CHECK_EQUAL(found, expected);
} }

View File

@ -36,23 +36,23 @@
#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/replace.hpp>
static CCriticalSection cs_wallets; static CCriticalSection cs_wallets;
static std::vector<CWallet*> vpwallets GUARDED_BY(cs_wallets); static std::vector<std::shared_ptr<CWallet>> vpwallets GUARDED_BY(cs_wallets);
bool AddWallet(CWallet* wallet) bool AddWallet(const std::shared_ptr<CWallet>& wallet)
{ {
LOCK(cs_wallets); LOCK(cs_wallets);
assert(wallet); assert(wallet);
std::vector<CWallet*>::const_iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet); std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
if (i != vpwallets.end()) return false; if (i != vpwallets.end()) return false;
vpwallets.push_back(wallet); vpwallets.push_back(wallet);
return true; return true;
} }
bool RemoveWallet(CWallet* wallet) bool RemoveWallet(const std::shared_ptr<CWallet>& wallet)
{ {
LOCK(cs_wallets); LOCK(cs_wallets);
assert(wallet); assert(wallet);
std::vector<CWallet*>::iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet); std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
if (i == vpwallets.end()) return false; if (i == vpwallets.end()) return false;
vpwallets.erase(i); vpwallets.erase(i);
return true; return true;
@ -64,16 +64,16 @@ bool HasWallets()
return !vpwallets.empty(); return !vpwallets.empty();
} }
std::vector<CWallet*> GetWallets() std::vector<std::shared_ptr<CWallet>> GetWallets()
{ {
LOCK(cs_wallets); LOCK(cs_wallets);
return vpwallets; return vpwallets;
} }
CWallet* GetWallet(const std::string& name) std::shared_ptr<CWallet> GetWallet(const std::string& name)
{ {
LOCK(cs_wallets); LOCK(cs_wallets);
for (CWallet* wallet : vpwallets) { for (const std::shared_ptr<CWallet>& wallet : vpwallets) {
if (wallet->GetName() == name) return wallet; if (wallet->GetName() == name) return wallet;
} }
return nullptr; return nullptr;
@ -3201,8 +3201,6 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
if (nLoadWalletRet != DBErrors::LOAD_OK) if (nLoadWalletRet != DBErrors::LOAD_OK)
return nLoadWalletRet; return nLoadWalletRet;
uiInterface.LoadWallet(this);
return DBErrors::LOAD_OK; return DBErrors::LOAD_OK;
} }
@ -4038,7 +4036,7 @@ bool CWallet::Verify(std::string wallet_file, bool salvage_wallet, std::string&
return WalletBatch::VerifyDatabaseFile(wallet_path, warning_string, error_string); return WalletBatch::VerifyDatabaseFile(wallet_path, warning_string, error_string);
} }
CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& path) std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name, const fs::path& path)
{ {
const std::string& walletFile = name; const std::string& walletFile = name;
@ -4060,10 +4058,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
int64_t nStart = GetTimeMillis(); int64_t nStart = GetTimeMillis();
bool fFirstRun = true; bool fFirstRun = true;
// Make a temporary wallet unique pointer so memory doesn't get leaked if std::shared_ptr<CWallet> walletInstance = std::make_shared<CWallet>(name, WalletDatabase::Create(path));
// wallet creation fails.
auto temp_wallet = MakeUnique<CWallet>(name, WalletDatabase::Create(path));
CWallet* walletInstance = temp_wallet.get();
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun); DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
if (nLoadWalletRet != DBErrors::LOAD_OK) if (nLoadWalletRet != DBErrors::LOAD_OK)
{ {
@ -4092,6 +4087,8 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
} }
} }
uiInterface.LoadWallet(walletInstance);
int prev_version = walletInstance->nWalletVersion; int prev_version = walletInstance->nWalletVersion;
if (gArgs.GetBoolArg("-upgradewallet", fFirstRun)) if (gArgs.GetBoolArg("-upgradewallet", fFirstRun))
{ {
@ -4304,7 +4301,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
nStart = GetTimeMillis(); nStart = GetTimeMillis();
{ {
WalletRescanReserver reserver(walletInstance); WalletRescanReserver reserver(walletInstance.get());
if (!reserver.reserve()) { if (!reserver.reserve()) {
InitError(_("Failed to rescan the wallet during initialization")); InitError(_("Failed to rescan the wallet during initialization"));
return nullptr; return nullptr;
@ -4342,7 +4339,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
} }
// Register with the validation interface. It's ok to do this after rescan since we're still holding cs_main. // 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)); walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));

View File

@ -32,11 +32,11 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
bool AddWallet(CWallet* wallet); bool AddWallet(const std::shared_ptr<CWallet>& wallet);
bool RemoveWallet(CWallet* wallet); bool RemoveWallet(const std::shared_ptr<CWallet>& wallet);
bool HasWallets(); bool HasWallets();
std::vector<CWallet*> GetWallets(); std::vector<std::shared_ptr<CWallet>> GetWallets();
CWallet* GetWallet(const std::string& name); std::shared_ptr<CWallet> GetWallet(const std::string& name);
//! Default for -keypool //! Default for -keypool
static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000; static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000;
@ -1122,7 +1122,7 @@ public:
static bool Verify(std::string wallet_file, bool salvage_wallet, std::string& error_string, std::string& warning_string); static bool Verify(std::string wallet_file, bool salvage_wallet, std::string& error_string, std::string& warning_string);
/* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */ /* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */
static CWallet* CreateWalletFromFile(const std::string& name, const fs::path& path); static std::shared_ptr<CWallet> CreateWalletFromFile(const std::string& name, const fs::path& path);
/** /**
* Wallet post-init setup * Wallet post-init setup

View File

@ -756,7 +756,7 @@ void MaybeCompactWalletDB()
return; return;
} }
for (CWallet* pwallet : GetWallets()) { for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
WalletDatabase& dbh = pwallet->GetDBHandle(); WalletDatabase& dbh = pwallet->GetDBHandle();
unsigned int nUpdateCounter = dbh.nUpdateCounter; unsigned int nUpdateCounter = dbh.nUpdateCounter;