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.
This commit is contained in:
Russell Yanofsky
2020-05-28 09:48:30 -04:00
parent b266b3e0bf
commit e4f4350471
20 changed files with 111 additions and 139 deletions

View File

@@ -314,24 +314,11 @@ public:
//! Set mock time.
virtual void setMockTime(int64_t time) = 0;
//! Return interfaces for accessing wallets (if any).
virtual std::vector<std::unique_ptr<Wallet>> getWallets() = 0;
};
//! Return implementation of Chain interface.
std::unique_ptr<Chain> MakeChain(NodeContext& node);
//! Return implementation of ChainClient interface for a wallet client. This
//! function will be undefined in builds where ENABLE_WALLET is false.
//!
//! Currently, wallets are the only chain clients. But in the future, other
//! types of chain clients could be added, such as tools for monitoring,
//! analysis, or fee estimation. These clients need to expose their own
//! MakeXXXClient functions returning their implementations of the ChainClient
//! interface.
std::unique_ptr<ChainClient> MakeWalletClient(Chain& chain, ArgsManager& args, std::vector<std::string> wallet_filenames);
} // namespace interfaces
#endif // BITCOIN_INTERFACES_CHAIN_H

View File

@@ -27,6 +27,7 @@
#include <support/allocators/secure.h>
#include <sync.h>
#include <txmempool.h>
#include <util/check.h>
#include <util/ref.h>
#include <util/system.h>
#include <util/translation.h>
@@ -41,16 +42,7 @@
#include <boost/signals2/signal.hpp>
class CWallet;
fs::path GetWalletDir();
std::vector<fs::path> ListWalletDir();
std::vector<std::shared_ptr<CWallet>> GetWallets();
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings);
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);
std::unique_ptr<interfaces::Handler> HandleLoadWallet(interfaces::Node::LoadWalletFn load_wallet);
namespace interfaces {
namespace {
class NodeImpl : public Node
@@ -239,36 +231,9 @@ public:
LOCK(::cs_main);
return ::ChainstateActive().CoinsTip().GetCoin(output, coin);
}
std::string getWalletDir() override
WalletClient& walletClient() override
{
return GetWalletDir().string();
}
std::vector<std::string> listWalletDir() override
{
std::vector<std::string> paths;
for (auto& path : ListWalletDir()) {
paths.push_back(path.string());
}
return paths;
}
std::vector<std::unique_ptr<Wallet>> getWallets() override
{
std::vector<std::unique_ptr<Wallet>> wallets;
for (auto& client : m_context->chain_clients) {
auto client_wallets = client->getWallets();
std::move(client_wallets.begin(), client_wallets.end(), std::back_inserter(wallets));
}
return wallets;
}
std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) override
{
return MakeWallet(LoadWallet(*m_context->chain, name, error, warnings));
}
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
{
std::shared_ptr<CWallet> wallet;
status = CreateWallet(*m_context->chain, passphrase, wallet_creation_flags, name, error, warnings, wallet);
return MakeWallet(wallet);
return *Assert(m_context->wallet_client);
}
std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override
{
@@ -286,10 +251,6 @@ public:
{
return MakeHandler(::uiInterface.ShowProgress_connect(fn));
}
std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) override
{
return HandleLoadWallet(std::move(fn));
}
std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override
{
return MakeHandler(::uiInterface.NotifyNumConnectionsChanged_connect(fn));

View File

@@ -29,14 +29,13 @@ class RPCTimerInterface;
class UniValue;
class proxyType;
enum class SynchronizationState;
enum class WalletCreationStatus;
struct CNodeStateStats;
struct NodeContext;
struct bilingual_str;
namespace interfaces {
class Handler;
class Wallet;
class WalletClient;
struct BlockTip;
//! Block and header tip information
@@ -173,22 +172,8 @@ public:
//! Get unspent outputs associated with a transaction.
virtual bool getUnspentOutput(const COutPoint& output, Coin& coin) = 0;
//! Return default wallet directory.
virtual std::string getWalletDir() = 0;
//! Return available wallets in wallet directory.
virtual std::vector<std::string> listWalletDir() = 0;
//! Return interfaces for accessing wallets (if any).
virtual std::vector<std::unique_ptr<Wallet>> getWallets() = 0;
//! Attempts to load a wallet from file or directory.
//! The loaded wallet is also notified to handlers previously registered
//! with handleLoadWallet.
virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
//! Create a wallet from file
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;
//! Get wallet client.
virtual WalletClient& walletClient() = 0;
//! Register handler for init messages.
using InitMessageFn = std::function<void(const std::string& message)>;
@@ -210,10 +195,6 @@ public:
using ShowProgressFn = std::function<void(const std::string& title, int progress, bool resume_possible)>;
virtual std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) = 0;
//! Register handler for load wallet messages.
using LoadWalletFn = std::function<void(std::unique_ptr<Wallet> wallet)>;
virtual std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) = 0;
//! Register handler for number of connections changed messages.
using NotifyNumConnectionsChangedFn = std::function<void(int new_num_connections)>;
virtual std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) = 0;

View File

@@ -485,7 +485,7 @@ public:
std::shared_ptr<CWallet> m_wallet;
};
class WalletClientImpl : public ChainClient
class WalletClientImpl : public WalletClient
{
public:
WalletClientImpl(Chain& chain, ArgsManager& args, std::vector<std::string> wallet_filenames)
@@ -494,6 +494,9 @@ public:
m_context.chain = &chain;
m_context.args = &args;
}
~WalletClientImpl() override { UnloadWallets(); }
//! ChainClient methods
void registerRpcs() override
{
for (const CRPCCommand& command : GetWalletRPCCommands()) {
@@ -509,6 +512,30 @@ public:
void flush() override { return FlushWallets(); }
void stop() override { return StopWallets(); }
void setMockTime(int64_t time) override { return SetMockTime(time); }
//! WalletClient methods
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
{
std::shared_ptr<CWallet> wallet;
status = CreateWallet(*m_context.chain, passphrase, wallet_creation_flags, name, error, warnings, wallet);
return MakeWallet(std::move(wallet));
}
std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) override
{
return MakeWallet(LoadWallet(*m_context.chain, WalletLocation(name), error, warnings));
}
std::string getWalletDir() override
{
return GetWalletDir().string();
}
std::vector<std::string> listWalletDir() override
{
std::vector<std::string> paths;
for (auto& path : ListWalletDir()) {
paths.push_back(path.string());
}
return paths;
}
std::vector<std::unique_ptr<Wallet>> getWallets() override
{
std::vector<std::unique_ptr<Wallet>> wallets;
@@ -517,7 +544,10 @@ public:
}
return wallets;
}
~WalletClientImpl() override { UnloadWallets(); }
std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) override
{
return HandleLoadWallet(std::move(fn));
}
WalletContext m_context;
const std::vector<std::string> m_wallet_filenames;
@@ -529,7 +559,7 @@ public:
std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet) { return wallet ? MakeUnique<WalletImpl>(wallet) : nullptr; }
std::unique_ptr<ChainClient> MakeWalletClient(Chain& chain, ArgsManager& args, std::vector<std::string> wallet_filenames)
std::unique_ptr<WalletClient> MakeWalletClient(Chain& chain, ArgsManager& args, std::vector<std::string> wallet_filenames)
{
return MakeUnique<WalletClientImpl>(chain, args, std::move(wallet_filenames));
}

View File

@@ -6,6 +6,7 @@
#define BITCOIN_INTERFACES_WALLET_H
#include <amount.h> // For CAmount
#include <interfaces/chain.h> // For ChainClient
#include <pubkey.h> // For CKeyID and CScriptID (definitions needed in CTxDestination instantiation)
#include <script/standard.h> // For CTxDestination
#include <support/allocators/secure.h> // For SecureString
@@ -28,9 +29,11 @@ class CWallet;
enum class FeeReason;
enum class OutputType;
enum class TransactionError;
enum class WalletCreationStatus;
enum isminetype : unsigned int;
struct CRecipient;
struct PartiallySignedTransaction;
struct WalletContext;
struct bilingual_str;
typedef uint8_t isminefilter;
@@ -301,6 +304,34 @@ public:
virtual CWallet* wallet() { return nullptr; }
};
//! Wallet chain client that in addition to having chain client methods for
//! starting up, shutting down, and registering RPCs, also has additional
//! methods (called by the GUI) to load and create wallets.
class WalletClient : public ChainClient
{
public:
//! Create new wallet.
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;
//! Load existing wallet.
virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
//! Return default wallet directory.
virtual std::string getWalletDir() = 0;
//! Return available wallets in wallet directory.
virtual std::vector<std::string> listWalletDir() = 0;
//! Return interfaces for accessing wallets (if any).
virtual std::vector<std::unique_ptr<Wallet>> getWallets() = 0;
//! Register handler for load wallet messages. This callback is triggered by
//! createWallet and loadWallet above, and also triggered when wallets are
//! loaded at startup or by RPC.
using LoadWalletFn = std::function<void(std::unique_ptr<Wallet> wallet)>;
virtual std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) = 0;
};
//! Information about one wallet address.
struct WalletAddress
{
@@ -379,6 +410,10 @@ struct WalletTxOut
//! dummywallet.cpp and throws if the wallet component is not compiled.
std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet);
//! Return implementation of ChainClient interface for a wallet client. This
//! function will be undefined in builds where ENABLE_WALLET is false.
std::unique_ptr<WalletClient> MakeWalletClient(Chain& chain, ArgsManager& args, std::vector<std::string> wallet_filenames);
} // namespace interfaces
#endif // BITCOIN_INTERFACES_WALLET_H