Skip to content

Commit e4f4350

Browse files
committed
refactor: Move wallet methods out of chain.h and node.h
Add WalletClient interface so node interface is cleaner and don't need wallet-specific methods. The new NodeContext::wallet_client pointer will also be needed to eliminate global wallet variables like ::vpwallets, because createWallet(), loadWallet(), getWallets(), etc methods called by the GUI need a way to get a reference to the list of open wallets if it is no longer a global variable. Also tweaks splash screen registration for load wallet events to be delayed until after wallet client is created.
1 parent b266b3e commit e4f4350

20 files changed

+111
-139
lines changed

src/dummywallet.cpp

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@
44

55
#include <util/system.h>
66
#include <walletinitinterface.h>
7-
#include <support/allocators/secure.h>
87

98
class CWallet;
10-
enum class WalletCreationStatus;
11-
struct bilingual_str;
129

1310
namespace interfaces {
1411
class Chain;
@@ -59,37 +56,6 @@ void DummyWalletInit::AddWalletOptions(ArgsManager& argsman) const
5956

6057
const WalletInitInterface& g_wallet_init_interface = DummyWalletInit();
6158

62-
fs::path GetWalletDir()
63-
{
64-
throw std::logic_error("Wallet function called in non-wallet build.");
65-
}
66-
67-
std::vector<fs::path> ListWalletDir()
68-
{
69-
throw std::logic_error("Wallet function called in non-wallet build.");
70-
}
71-
72-
std::vector<std::shared_ptr<CWallet>> GetWallets()
73-
{
74-
throw std::logic_error("Wallet function called in non-wallet build.");
75-
}
76-
77-
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings)
78-
{
79-
throw std::logic_error("Wallet function called in non-wallet build.");
80-
}
81-
82-
WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings, std::shared_ptr<CWallet>& result)
83-
{
84-
throw std::logic_error("Wallet function called in non-wallet build.");
85-
}
86-
87-
using LoadWalletFn = std::function<void(std::unique_ptr<interfaces::Wallet> wallet)>;
88-
std::unique_ptr<interfaces::Handler> HandleLoadWallet(LoadWalletFn load_wallet)
89-
{
90-
throw std::logic_error("Wallet function called in non-wallet build.");
91-
}
92-
9359
namespace interfaces {
9460

9561
std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet)

src/interfaces/chain.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -314,24 +314,11 @@ class ChainClient
314314

315315
//! Set mock time.
316316
virtual void setMockTime(int64_t time) = 0;
317-
318-
//! Return interfaces for accessing wallets (if any).
319-
virtual std::vector<std::unique_ptr<Wallet>> getWallets() = 0;
320317
};
321318

322319
//! Return implementation of Chain interface.
323320
std::unique_ptr<Chain> MakeChain(NodeContext& node);
324321

325-
//! Return implementation of ChainClient interface for a wallet client. This
326-
//! function will be undefined in builds where ENABLE_WALLET is false.
327-
//!
328-
//! Currently, wallets are the only chain clients. But in the future, other
329-
//! types of chain clients could be added, such as tools for monitoring,
330-
//! analysis, or fee estimation. These clients need to expose their own
331-
//! MakeXXXClient functions returning their implementations of the ChainClient
332-
//! interface.
333-
std::unique_ptr<ChainClient> MakeWalletClient(Chain& chain, ArgsManager& args, std::vector<std::string> wallet_filenames);
334-
335322
} // namespace interfaces
336323

337324
#endif // BITCOIN_INTERFACES_CHAIN_H

src/interfaces/node.cpp

Lines changed: 3 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <support/allocators/secure.h>
2828
#include <sync.h>
2929
#include <txmempool.h>
30+
#include <util/check.h>
3031
#include <util/ref.h>
3132
#include <util/system.h>
3233
#include <util/translation.h>
@@ -41,16 +42,7 @@
4142

4243
#include <boost/signals2/signal.hpp>
4344

44-
class CWallet;
45-
fs::path GetWalletDir();
46-
std::vector<fs::path> ListWalletDir();
47-
std::vector<std::shared_ptr<CWallet>> GetWallets();
48-
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings);
49-
WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings, std::shared_ptr<CWallet>& result);
50-
std::unique_ptr<interfaces::Handler> HandleLoadWallet(interfaces::Node::LoadWalletFn load_wallet);
51-
5245
namespace interfaces {
53-
5446
namespace {
5547

5648
class NodeImpl : public Node
@@ -239,36 +231,9 @@ class NodeImpl : public Node
239231
LOCK(::cs_main);
240232
return ::ChainstateActive().CoinsTip().GetCoin(output, coin);
241233
}
242-
std::string getWalletDir() override
243-
{
244-
return GetWalletDir().string();
245-
}
246-
std::vector<std::string> listWalletDir() override
247-
{
248-
std::vector<std::string> paths;
249-
for (auto& path : ListWalletDir()) {
250-
paths.push_back(path.string());
251-
}
252-
return paths;
253-
}
254-
std::vector<std::unique_ptr<Wallet>> getWallets() override
234+
WalletClient& walletClient() override
255235
{
256-
std::vector<std::unique_ptr<Wallet>> wallets;
257-
for (auto& client : m_context->chain_clients) {
258-
auto client_wallets = client->getWallets();
259-
std::move(client_wallets.begin(), client_wallets.end(), std::back_inserter(wallets));
260-
}
261-
return wallets;
262-
}
263-
std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) override
264-
{
265-
return MakeWallet(LoadWallet(*m_context->chain, name, error, warnings));
266-
}
267-
std::unique_ptr<Wallet> createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings, WalletCreationStatus& status) override
268-
{
269-
std::shared_ptr<CWallet> wallet;
270-
status = CreateWallet(*m_context->chain, passphrase, wallet_creation_flags, name, error, warnings, wallet);
271-
return MakeWallet(wallet);
236+
return *Assert(m_context->wallet_client);
272237
}
273238
std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override
274239
{
@@ -286,10 +251,6 @@ class NodeImpl : public Node
286251
{
287252
return MakeHandler(::uiInterface.ShowProgress_connect(fn));
288253
}
289-
std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) override
290-
{
291-
return HandleLoadWallet(std::move(fn));
292-
}
293254
std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override
294255
{
295256
return MakeHandler(::uiInterface.NotifyNumConnectionsChanged_connect(fn));

src/interfaces/node.h

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,13 @@ class RPCTimerInterface;
2929
class UniValue;
3030
class proxyType;
3131
enum class SynchronizationState;
32-
enum class WalletCreationStatus;
3332
struct CNodeStateStats;
3433
struct NodeContext;
3534
struct bilingual_str;
3635

3736
namespace interfaces {
3837
class Handler;
39-
class Wallet;
38+
class WalletClient;
4039
struct BlockTip;
4140

4241
//! Block and header tip information
@@ -173,22 +172,8 @@ class Node
173172
//! Get unspent outputs associated with a transaction.
174173
virtual bool getUnspentOutput(const COutPoint& output, Coin& coin) = 0;
175174

176-
//! Return default wallet directory.
177-
virtual std::string getWalletDir() = 0;
178-
179-
//! Return available wallets in wallet directory.
180-
virtual std::vector<std::string> listWalletDir() = 0;
181-
182-
//! Return interfaces for accessing wallets (if any).
183-
virtual std::vector<std::unique_ptr<Wallet>> getWallets() = 0;
184-
185-
//! Attempts to load a wallet from file or directory.
186-
//! The loaded wallet is also notified to handlers previously registered
187-
//! with handleLoadWallet.
188-
virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
189-
190-
//! Create a wallet from file
191-
virtual std::unique_ptr<Wallet> createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings, WalletCreationStatus& status) = 0;
175+
//! Get wallet client.
176+
virtual WalletClient& walletClient() = 0;
192177

193178
//! Register handler for init messages.
194179
using InitMessageFn = std::function<void(const std::string& message)>;
@@ -210,10 +195,6 @@ class Node
210195
using ShowProgressFn = std::function<void(const std::string& title, int progress, bool resume_possible)>;
211196
virtual std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) = 0;
212197

213-
//! Register handler for load wallet messages.
214-
using LoadWalletFn = std::function<void(std::unique_ptr<Wallet> wallet)>;
215-
virtual std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) = 0;
216-
217198
//! Register handler for number of connections changed messages.
218199
using NotifyNumConnectionsChangedFn = std::function<void(int new_num_connections)>;
219200
virtual std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) = 0;

src/interfaces/wallet.cpp

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ class WalletImpl : public Wallet
485485
std::shared_ptr<CWallet> m_wallet;
486486
};
487487

488-
class WalletClientImpl : public ChainClient
488+
class WalletClientImpl : public WalletClient
489489
{
490490
public:
491491
WalletClientImpl(Chain& chain, ArgsManager& args, std::vector<std::string> wallet_filenames)
@@ -494,6 +494,9 @@ class WalletClientImpl : public ChainClient
494494
m_context.chain = &chain;
495495
m_context.args = &args;
496496
}
497+
~WalletClientImpl() override { UnloadWallets(); }
498+
499+
//! ChainClient methods
497500
void registerRpcs() override
498501
{
499502
for (const CRPCCommand& command : GetWalletRPCCommands()) {
@@ -509,6 +512,30 @@ class WalletClientImpl : public ChainClient
509512
void flush() override { return FlushWallets(); }
510513
void stop() override { return StopWallets(); }
511514
void setMockTime(int64_t time) override { return SetMockTime(time); }
515+
516+
//! WalletClient methods
517+
std::unique_ptr<Wallet> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, WalletCreationStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings) override
518+
{
519+
std::shared_ptr<CWallet> wallet;
520+
status = CreateWallet(*m_context.chain, passphrase, wallet_creation_flags, name, error, warnings, wallet);
521+
return MakeWallet(std::move(wallet));
522+
}
523+
std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) override
524+
{
525+
return MakeWallet(LoadWallet(*m_context.chain, WalletLocation(name), error, warnings));
526+
}
527+
std::string getWalletDir() override
528+
{
529+
return GetWalletDir().string();
530+
}
531+
std::vector<std::string> listWalletDir() override
532+
{
533+
std::vector<std::string> paths;
534+
for (auto& path : ListWalletDir()) {
535+
paths.push_back(path.string());
536+
}
537+
return paths;
538+
}
512539
std::vector<std::unique_ptr<Wallet>> getWallets() override
513540
{
514541
std::vector<std::unique_ptr<Wallet>> wallets;
@@ -517,7 +544,10 @@ class WalletClientImpl : public ChainClient
517544
}
518545
return wallets;
519546
}
520-
~WalletClientImpl() override { UnloadWallets(); }
547+
std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) override
548+
{
549+
return HandleLoadWallet(std::move(fn));
550+
}
521551

522552
WalletContext m_context;
523553
const std::vector<std::string> m_wallet_filenames;
@@ -529,7 +559,7 @@ class WalletClientImpl : public ChainClient
529559

530560
std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet) { return wallet ? MakeUnique<WalletImpl>(wallet) : nullptr; }
531561

532-
std::unique_ptr<ChainClient> MakeWalletClient(Chain& chain, ArgsManager& args, std::vector<std::string> wallet_filenames)
562+
std::unique_ptr<WalletClient> MakeWalletClient(Chain& chain, ArgsManager& args, std::vector<std::string> wallet_filenames)
533563
{
534564
return MakeUnique<WalletClientImpl>(chain, args, std::move(wallet_filenames));
535565
}

src/interfaces/wallet.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#define BITCOIN_INTERFACES_WALLET_H
77

88
#include <amount.h> // For CAmount
9+
#include <interfaces/chain.h> // For ChainClient
910
#include <pubkey.h> // For CKeyID and CScriptID (definitions needed in CTxDestination instantiation)
1011
#include <script/standard.h> // For CTxDestination
1112
#include <support/allocators/secure.h> // For SecureString
@@ -28,9 +29,11 @@ class CWallet;
2829
enum class FeeReason;
2930
enum class OutputType;
3031
enum class TransactionError;
32+
enum class WalletCreationStatus;
3133
enum isminetype : unsigned int;
3234
struct CRecipient;
3335
struct PartiallySignedTransaction;
36+
struct WalletContext;
3437
struct bilingual_str;
3538
typedef uint8_t isminefilter;
3639

@@ -301,6 +304,34 @@ class Wallet
301304
virtual CWallet* wallet() { return nullptr; }
302305
};
303306

307+
//! Wallet chain client that in addition to having chain client methods for
308+
//! starting up, shutting down, and registering RPCs, also has additional
309+
//! methods (called by the GUI) to load and create wallets.
310+
class WalletClient : public ChainClient
311+
{
312+
public:
313+
//! Create new wallet.
314+
virtual std::unique_ptr<Wallet> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, WalletCreationStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
315+
316+
//! Load existing wallet.
317+
virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
318+
319+
//! Return default wallet directory.
320+
virtual std::string getWalletDir() = 0;
321+
322+
//! Return available wallets in wallet directory.
323+
virtual std::vector<std::string> listWalletDir() = 0;
324+
325+
//! Return interfaces for accessing wallets (if any).
326+
virtual std::vector<std::unique_ptr<Wallet>> getWallets() = 0;
327+
328+
//! Register handler for load wallet messages. This callback is triggered by
329+
//! createWallet and loadWallet above, and also triggered when wallets are
330+
//! loaded at startup or by RPC.
331+
using LoadWalletFn = std::function<void(std::unique_ptr<Wallet> wallet)>;
332+
virtual std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) = 0;
333+
};
334+
304335
//! Information about one wallet address.
305336
struct WalletAddress
306337
{
@@ -379,6 +410,10 @@ struct WalletTxOut
379410
//! dummywallet.cpp and throws if the wallet component is not compiled.
380411
std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet);
381412

413+
//! Return implementation of ChainClient interface for a wallet client. This
414+
//! function will be undefined in builds where ENABLE_WALLET is false.
415+
std::unique_ptr<WalletClient> MakeWalletClient(Chain& chain, ArgsManager& args, std::vector<std::string> wallet_filenames);
416+
382417
} // namespace interfaces
383418

384419
#endif // BITCOIN_INTERFACES_WALLET_H

src/node/context.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class PeerLogicValidation;
2020
namespace interfaces {
2121
class Chain;
2222
class ChainClient;
23+
class WalletClient;
2324
} // namespace interfaces
2425

2526
//! NodeContext struct containing references to chain state and connection
@@ -40,7 +41,11 @@ struct NodeContext {
4041
std::unique_ptr<BanMan> banman;
4142
ArgsManager* args{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
4243
std::unique_ptr<interfaces::Chain> chain;
44+
//! List of all chain clients (wallet processes or other client) connected to node.
4345
std::vector<std::unique_ptr<interfaces::ChainClient>> chain_clients;
46+
//! Reference to chain client that should used to load or create wallets
47+
//! opened by the gui.
48+
interfaces::WalletClient* wallet_client{nullptr};
4449
std::unique_ptr<CScheduler> scheduler;
4550
std::function<void()> rpc_interruption_point = [] {};
4651

src/qt/bitcoin.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle)
266266
// We don't hold a direct pointer to the splash screen after creation, but the splash
267267
// screen will take care of deleting itself when finish() happens.
268268
m_splash->show();
269+
connect(this, &BitcoinApplication::requestedInitialize, m_splash, &SplashScreen::handleLoadWallet);
269270
connect(this, &BitcoinApplication::splashFinished, m_splash, &SplashScreen::finish);
270271
connect(this, &BitcoinApplication::requestedShutdown, m_splash, &QWidget::close);
271272
}

src/qt/bitcoingui.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1189,7 +1189,7 @@ void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmoun
11891189
// On new transaction, make an info balloon
11901190
QString msg = tr("Date: %1\n").arg(date) +
11911191
tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(unit, amount, true));
1192-
if (m_node.getWallets().size() > 1 && !walletName.isEmpty()) {
1192+
if (m_node.walletClient().getWallets().size() > 1 && !walletName.isEmpty()) {
11931193
msg += tr("Wallet: %1\n").arg(walletName);
11941194
}
11951195
msg += tr("Type: %1\n").arg(type);

src/qt/splashscreen.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,12 @@ void SplashScreen::subscribeToCoreSignals()
198198
// Connect signals to client
199199
m_handler_init_message = m_node->handleInitMessage(std::bind(InitMessage, this, std::placeholders::_1));
200200
m_handler_show_progress = m_node->handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
201+
}
202+
203+
void SplashScreen::handleLoadWallet()
204+
{
201205
#ifdef ENABLE_WALLET
202-
m_handler_load_wallet = m_node->handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) { ConnectWallet(std::move(wallet)); });
206+
m_handler_load_wallet = m_node->walletClient().handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) { ConnectWallet(std::move(wallet)); });
203207
#endif
204208
}
205209

0 commit comments

Comments
 (0)