Merge #13017: Add wallets management functions

3c058fd wallet: Add HasWallets (João Barbosa)
373aee2 wallet: Add AddWallet, RemoveWallet, GetWallet and GetWallets (João Barbosa)
6efd964 refactor: Drop CWalletRef typedef (João Barbosa)

Pull request description:

  This is a small step towards dynamic wallet load/unload. The wallets *registry* `vpwallets` is used in several places. With these new functions all `vpwallets` usage are removed and `vpwallets` is now a static variable (no external linkage).

  The typedef `CWalletRef` is also removed as it is narrowly used.

Tree-SHA512: 2ea19da2e17b521ad678bfe10f3257e497ccaf7ab9fd0b6647f9d829f1d6131cfa68db8e8492421711c6da399859432b963a568bdd4ca40a77dd95b597839423
This commit is contained in:
Wladimir J. van der Laan 2018-04-23 07:58:41 +02:00
commit 65d7083f15
No known key found for this signature in database
GPG key ID: 1E4AED62986CD25D
9 changed files with 80 additions and 41 deletions

View file

@ -236,7 +236,7 @@ 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 (CWalletRef wallet : ::vpwallets) { for (CWallet* wallet : GetWallets()) {
wallets.emplace_back(MakeWallet(*wallet)); wallets.emplace_back(MakeWallet(*wallet));
} }
return wallets; return wallets;

View file

@ -180,9 +180,9 @@ void TestGUI()
TransactionView transactionView(platformStyle.get()); TransactionView transactionView(platformStyle.get());
auto node = interfaces::MakeNode(); auto node = interfaces::MakeNode();
OptionsModel optionsModel(*node); OptionsModel optionsModel(*node);
vpwallets.insert(vpwallets.begin(), &wallet); AddWallet(&wallet);
WalletModel walletModel(std::move(node->getWallets()[0]), *node, platformStyle.get(), &optionsModel); WalletModel walletModel(std::move(node->getWallets().back()), *node, platformStyle.get(), &optionsModel);
vpwallets.erase(vpwallets.begin()); RemoveWallet(&wallet);
sendCoinsDialog.setModel(&walletModel); sendCoinsDialog.setModel(&walletModel);
transactionView.setModel(&walletModel); transactionView.setModel(&walletModel);

View file

@ -69,7 +69,7 @@ UniValue validateaddress(const JSONRPCRequest& request)
{ {
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
if (!::vpwallets.empty() && IsDeprecatedRPCEnabled("validateaddress")) { if (HasWallets() && IsDeprecatedRPCEnabled("validateaddress")) {
ret.pushKVs(getaddressinfo(request)); ret.pushKVs(getaddressinfo(request));
} }
#endif #endif

View file

@ -315,7 +315,7 @@ bool WalletInit::Open() const
if (!pwallet) { if (!pwallet) {
return false; return false;
} }
vpwallets.push_back(pwallet); AddWallet(pwallet);
} }
return true; return true;
@ -323,29 +323,29 @@ bool WalletInit::Open() const
void WalletInit::Start(CScheduler& scheduler) const void WalletInit::Start(CScheduler& scheduler) const
{ {
for (CWalletRef pwallet : vpwallets) { for (CWallet* pwallet : GetWallets()) {
pwallet->postInitProcess(scheduler); pwallet->postInitProcess(scheduler);
} }
} }
void WalletInit::Flush() const void WalletInit::Flush() const
{ {
for (CWalletRef pwallet : vpwallets) { for (CWallet* pwallet : GetWallets()) {
pwallet->Flush(false); pwallet->Flush(false);
} }
} }
void WalletInit::Stop() const void WalletInit::Stop() const
{ {
for (CWalletRef pwallet : vpwallets) { for (CWallet* pwallet : GetWallets()) {
pwallet->Flush(true); pwallet->Flush(true);
} }
} }
void WalletInit::Close() const void WalletInit::Close() const
{ {
for (CWalletRef pwallet : vpwallets) { for (CWallet* pwallet : GetWallets()) {
RemoveWallet(pwallet);
delete pwallet; delete pwallet;
} }
vpwallets.clear();
} }

View file

@ -46,14 +46,13 @@ 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()));
for (CWalletRef pwallet : ::vpwallets) { CWallet* pwallet = GetWallet(requestedWallet);
if (pwallet->GetName() == requestedWallet) { if (!pwallet) throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
return pwallet; return pwallet;
} }
}
throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded"); std::vector<CWallet*> wallets = GetWallets();
} return wallets.size() == 1 || (request.fHelp && wallets.size() > 0) ? wallets[0] : nullptr;
return ::vpwallets.size() == 1 || (request.fHelp && ::vpwallets.size() > 0) ? ::vpwallets[0] : nullptr;
} }
std::string HelpRequiringPassphrase(CWallet * const pwallet) std::string HelpRequiringPassphrase(CWallet * const pwallet)
@ -67,7 +66,7 @@ bool EnsureWalletIsAvailable(CWallet * const pwallet, bool avoidException)
{ {
if (pwallet) return true; if (pwallet) return true;
if (avoidException) return false; if (avoidException) return false;
if (::vpwallets.empty()) { if (!HasWallets()) {
// Note: It isn't currently possible to trigger this error because // Note: It isn't currently possible to trigger this error because
// wallet RPC methods aren't registered unless a wallet is loaded. But // wallet RPC methods aren't registered unless a wallet is loaded. But
// this error is being kept as a precaution, because it's possible in // this error is being kept as a precaution, because it's possible in
@ -2862,8 +2861,7 @@ UniValue listwallets(const JSONRPCRequest& request)
UniValue obj(UniValue::VARR); UniValue obj(UniValue::VARR);
for (CWalletRef pwallet : vpwallets) { for (CWallet* pwallet : GetWallets()) {
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue; return NullUniValue;
} }

View file

@ -74,7 +74,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
// after. // after.
{ {
CWallet wallet("dummy", WalletDatabase::CreateDummy()); CWallet wallet("dummy", WalletDatabase::CreateDummy());
vpwallets.insert(vpwallets.begin(), &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));
vpwallets.erase(vpwallets.begin()); RemoveWallet(&wallet);
} }
} }
@ -140,9 +140,9 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
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());
vpwallets.insert(vpwallets.begin(), &wallet); AddWallet(&wallet);
::dumpwallet(request); ::dumpwallet(request);
vpwallets.erase(vpwallets.begin()); RemoveWallet(&wallet);
} }
// Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME // Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME
@ -153,9 +153,9 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
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());
vpwallets.insert(vpwallets.begin(), &wallet); AddWallet(&wallet);
::importwallet(request); ::importwallet(request);
vpwallets.erase(vpwallets.begin()); RemoveWallet(&wallet);
LOCK(wallet.cs_wallet); LOCK(wallet.cs_wallet);
BOOST_CHECK_EQUAL(wallet.mapWallet.size(), 3U); BOOST_CHECK_EQUAL(wallet.mapWallet.size(), 3U);

View file

@ -28,12 +28,50 @@
#include <utilmoneystr.h> #include <utilmoneystr.h>
#include <wallet/fees.h> #include <wallet/fees.h>
#include <algorithm>
#include <assert.h> #include <assert.h>
#include <future> #include <future>
#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/replace.hpp>
std::vector<CWalletRef> vpwallets; static std::vector<CWallet*> vpwallets;
bool AddWallet(CWallet* wallet)
{
assert(wallet);
std::vector<CWallet*>::const_iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
if (i != vpwallets.end()) return false;
vpwallets.push_back(wallet);
return true;
}
bool RemoveWallet(CWallet* wallet)
{
assert(wallet);
std::vector<CWallet*>::iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
if (i == vpwallets.end()) return false;
vpwallets.erase(i);
return true;
}
bool HasWallets()
{
return !vpwallets.empty();
}
std::vector<CWallet*> GetWallets()
{
return vpwallets;
}
CWallet* GetWallet(const std::string& name)
{
for (CWallet* wallet : vpwallets) {
if (wallet->GetName() == name) return wallet;
}
return nullptr;
}
/** Transaction fee set by the user */ /** Transaction fee set by the user */
CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET;

View file

@ -32,8 +32,11 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
typedef CWallet* CWalletRef; bool AddWallet(CWallet* wallet);
extern std::vector<CWalletRef> vpwallets; bool RemoveWallet(CWallet* wallet);
bool HasWallets();
std::vector<CWallet*> GetWallets();
CWallet* GetWallet(const std::string& name);
/** /**
* Settings * Settings
@ -1230,10 +1233,10 @@ std::vector<CTxDestination> GetAllDestinationsForKey(const CPubKey& key);
class WalletRescanReserver class WalletRescanReserver
{ {
private: private:
CWalletRef m_wallet; CWallet* m_wallet;
bool m_could_reserve; bool m_could_reserve;
public: public:
explicit WalletRescanReserver(CWalletRef w) : m_wallet(w), m_could_reserve(false) {} explicit WalletRescanReserver(CWallet* w) : m_wallet(w), m_could_reserve(false) {}
bool reserve() bool reserve()
{ {

View file

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