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
std::vector<std::unique_ptr<Wallet>> wallets;
for (CWalletRef wallet : ::vpwallets) {
for (CWallet* wallet : GetWallets()) {
wallets.emplace_back(MakeWallet(*wallet));
}
return wallets;

View file

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

View file

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

View file

@ -315,7 +315,7 @@ bool WalletInit::Open() const
if (!pwallet) {
return false;
}
vpwallets.push_back(pwallet);
AddWallet(pwallet);
}
return true;
@ -323,29 +323,29 @@ bool WalletInit::Open() const
void WalletInit::Start(CScheduler& scheduler) const
{
for (CWalletRef pwallet : vpwallets) {
for (CWallet* pwallet : GetWallets()) {
pwallet->postInitProcess(scheduler);
}
}
void WalletInit::Flush() const
{
for (CWalletRef pwallet : vpwallets) {
for (CWallet* pwallet : GetWallets()) {
pwallet->Flush(false);
}
}
void WalletInit::Stop() const
{
for (CWalletRef pwallet : vpwallets) {
for (CWallet* pwallet : GetWallets()) {
pwallet->Flush(true);
}
}
void WalletInit::Close() const
{
for (CWalletRef pwallet : vpwallets) {
for (CWallet* pwallet : GetWallets()) {
RemoveWallet(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) {
// wallet endpoint was used
std::string requestedWallet = urlDecode(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
for (CWalletRef pwallet : ::vpwallets) {
if (pwallet->GetName() == requestedWallet) {
return pwallet;
}
}
throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
CWallet* pwallet = GetWallet(requestedWallet);
if (!pwallet) throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
return pwallet;
}
return ::vpwallets.size() == 1 || (request.fHelp && ::vpwallets.size() > 0) ? ::vpwallets[0] : nullptr;
std::vector<CWallet*> wallets = GetWallets();
return wallets.size() == 1 || (request.fHelp && wallets.size() > 0) ? wallets[0] : nullptr;
}
std::string HelpRequiringPassphrase(CWallet * const pwallet)
@ -67,7 +66,7 @@ bool EnsureWalletIsAvailable(CWallet * const pwallet, bool avoidException)
{
if (pwallet) return true;
if (avoidException) return false;
if (::vpwallets.empty()) {
if (!HasWallets()) {
// Note: It isn't currently possible to trigger this error because
// 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
@ -2862,8 +2861,7 @@ UniValue listwallets(const JSONRPCRequest& request)
UniValue obj(UniValue::VARR);
for (CWalletRef pwallet : vpwallets) {
for (CWallet* pwallet : GetWallets()) {
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}

View file

@ -74,7 +74,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
// after.
{
CWallet wallet("dummy", WalletDatabase::CreateDummy());
vpwallets.insert(vpwallets.begin(), &wallet);
AddWallet(&wallet);
UniValue keys;
keys.setArray();
UniValue key;
@ -105,7 +105,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
"downloading and rescanning the relevant blocks (see -reindex and -rescan "
"options).\"}},{\"success\":true}]",
0, oldTip->GetBlockTimeMax(), TIMESTAMP_WINDOW));
vpwallets.erase(vpwallets.begin());
RemoveWallet(&wallet);
}
}
@ -140,9 +140,9 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
JSONRPCRequest request;
request.params.setArray();
request.params.push_back((pathTemp / "wallet.backup").string());
vpwallets.insert(vpwallets.begin(), &wallet);
AddWallet(&wallet);
::dumpwallet(request);
vpwallets.erase(vpwallets.begin());
RemoveWallet(&wallet);
}
// Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME
@ -153,9 +153,9 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
JSONRPCRequest request;
request.params.setArray();
request.params.push_back((pathTemp / "wallet.backup").string());
vpwallets.insert(vpwallets.begin(), &wallet);
AddWallet(&wallet);
::importwallet(request);
vpwallets.erase(vpwallets.begin());
RemoveWallet(&wallet);
LOCK(wallet.cs_wallet);
BOOST_CHECK_EQUAL(wallet.mapWallet.size(), 3U);

View file

@ -28,12 +28,50 @@
#include <utilmoneystr.h>
#include <wallet/fees.h>
#include <algorithm>
#include <assert.h>
#include <future>
#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 */
CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET;

View file

@ -32,8 +32,11 @@
#include <utility>
#include <vector>
typedef CWallet* CWalletRef;
extern std::vector<CWalletRef> vpwallets;
bool AddWallet(CWallet* wallet);
bool RemoveWallet(CWallet* wallet);
bool HasWallets();
std::vector<CWallet*> GetWallets();
CWallet* GetWallet(const std::string& name);
/**
* Settings
@ -268,7 +271,7 @@ public:
//Get the marginal bytes of spending the specified output
int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* pwallet);
/**
/**
* A transaction with a bunch of additional info that only the owner cares about.
* It includes any unrecorded transactions needed to link it back to the block chain.
*/
@ -653,7 +656,7 @@ struct CoinEligibilityFilter
};
class WalletRescanReserver; //forward declarations for ScanForWalletTransactions/RescanFromTime
/**
/**
* A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
* and provides the ability to create new transactions.
*/
@ -903,7 +906,7 @@ public:
void GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) const;
unsigned int ComputeTimeSmart(const CWalletTx& wtx) const;
/**
/**
* Increment the next transaction order id
* @return next transaction order id
*/
@ -1032,7 +1035,7 @@ public:
}
void GetScriptForMining(std::shared_ptr<CReserveScript> &script);
unsigned int GetKeyPoolSize()
{
AssertLockHeld(cs_wallet); // set{Ex,In}ternalKeyPool
@ -1057,7 +1060,7 @@ public:
//! Flush wallet (bitdb flush)
void Flush(bool shutdown=false);
/**
/**
* Address book entry changed.
* @note called with lock cs_wallet held.
*/
@ -1066,7 +1069,7 @@ public:
const std::string &purpose,
ChangeType status)> NotifyAddressBookChanged;
/**
/**
* Wallet transaction added, removed or updated.
* @note called with lock cs_wallet held.
*/
@ -1113,7 +1116,7 @@ public:
/* Generates a new HD master key (will not be activated) */
CPubKey GenerateNewHDMasterKey();
/* Set the current HD master key (will reset the chain child index counters)
Sets the master key's version based on the current wallet version (so the
caller must ensure the current wallet version is correct before calling
@ -1184,7 +1187,7 @@ public:
};
/**
/**
* DEPRECATED Account information.
* Stored in wallet with key "acc"+string account name.
*/
@ -1230,10 +1233,10 @@ std::vector<CTxDestination> GetAllDestinationsForKey(const CPubKey& key);
class WalletRescanReserver
{
private:
CWalletRef m_wallet;
CWallet* m_wallet;
bool m_could_reserve;
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()
{

View file

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