diff --git a/src/Makefile.am b/src/Makefile.am --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,6 +7,7 @@ AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(HARDENED_LDFLAGS) $(SANITIZER_LDFLAGS) AM_CXXFLAGS = $(DEBUG_CXXFLAGS) $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS) $(SANITIZER_CXXFLAGS) AM_CPPFLAGS = $(DEBUG_CPPFLAGS) $(HARDENED_CPPFLAGS) +AM_LIBTOOLFLAGS = --preserve-dup-deps EXTRA_LIBRARIES = if EMBEDDED_UNIVALUE @@ -143,6 +144,7 @@ init.h \ interfaces/handler.h \ interfaces/node.h \ + interfaces/wallet.h \ key.h \ keystore.h \ dbwrapper.h \ @@ -296,6 +298,7 @@ libbitcoin_wallet_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_wallet_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_wallet_a_SOURCES = \ + interfaces/wallet.cpp \ wallet/crypter.cpp \ wallet/db.cpp \ wallet/finaltx.cpp \ diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -399,7 +399,7 @@ endif qt_bitcoin_qt_LDADD = qt/libbitcoinqt.a $(LIBBITCOIN_SERVER) if ENABLE_WALLET -qt_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET) +qt_bitcoin_qt_LDADD += $(LIBBITCOIN_UTIL) $(LIBBITCOIN_WALLET) endif if ENABLE_ZMQ qt_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) @@ -408,7 +408,7 @@ $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) qt_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -qt_bitcoin_qt_LIBTOOLFLAGS = --tag CXX +qt_bitcoin_qt_LIBTOOLFLAGS = $(AM_LIBTOOLFLAGS) --tag CXX #locale/foo.ts -> locale/foo.qm QT_QM=$(QT_TS:.ts=.qm) diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -58,7 +58,7 @@ qt_test_test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER) if ENABLE_WALLET -qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET) +qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_UTIL) $(LIBBITCOIN_WALLET) endif if ENABLE_ZMQ qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) diff --git a/src/interfaces/node.h b/src/interfaces/node.h --- a/src/interfaces/node.h +++ b/src/interfaces/node.h @@ -20,6 +20,7 @@ namespace interfaces { class Handler; +class Wallet; //! Top-level interface for a bitcoin node (bitcoind process). class Node { @@ -92,6 +93,15 @@ const std::string &message, const std::string &non_interactive_message, const std::string &caption, unsigned int style)>; virtual std::unique_ptr handleQuestion(QuestionFn fn) = 0; + + //! Register handler for progress messages. + using ShowProgressFn = std::function; + virtual std::unique_ptr handleShowProgress(ShowProgressFn fn) = 0; + + //! Register handler for load wallet messages. + using LoadWalletFn = std::function wallet)>; + virtual std::unique_ptr handleLoadWallet(LoadWalletFn fn) = 0; }; //! Return implementation of Node interface. diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp --- a/src/interfaces/node.cpp +++ b/src/interfaces/node.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -16,8 +17,19 @@ #include #include +#if defined(HAVE_CONFIG_H) +#include +#endif +#ifdef ENABLE_WALLET +#define CHECK_WALLET(x) x +#else +#define CHECK_WALLET(x) \ + throw std::logic_error("Wallet function called in non-wallet build.") +#endif + #include +class CWallet; class HTTPRPCRequestProcessor; namespace interfaces { @@ -84,6 +96,14 @@ std::unique_ptr handleQuestion(QuestionFn fn) override { return MakeHandler(::uiInterface.ThreadSafeQuestion.connect(fn)); } + std::unique_ptr + handleShowProgress(ShowProgressFn fn) override { + return MakeHandler(::uiInterface.ShowProgress.connect(fn)); + } + std::unique_ptr handleLoadWallet(LoadWalletFn fn) override { + CHECK_WALLET(return MakeHandler(::uiInterface.LoadWallet.connect( + [fn](CWallet *wallet) { fn(MakeWallet(*wallet)); }))); + } }; } // namespace diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h new file mode 100644 --- /dev/null +++ b/src/interfaces/wallet.h @@ -0,0 +1,35 @@ +// Copyright (c) 2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_INTERFACES_WALLET_H +#define BITCOIN_INTERFACES_WALLET_H + +#include +#include +#include + +class CWallet; + +namespace interfaces { + +class Handler; + +//! Interface for accessing a wallet. +class Wallet { +public: + virtual ~Wallet() {} + + //! Register handler for show progress messages. + using ShowProgressFn = + std::function; + virtual std::unique_ptr handleShowProgress(ShowProgressFn fn) = 0; +}; + +//! Return implementation of Wallet interface. This function will be undefined +//! in builds where ENABLE_WALLET is false. +std::unique_ptr MakeWallet(CWallet &wallet); + +} // namespace interfaces + +#endif // BITCOIN_INTERFACES_WALLET_H diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp new file mode 100644 --- /dev/null +++ b/src/interfaces/wallet.cpp @@ -0,0 +1,33 @@ +// Copyright (c) 2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include + +#include + +namespace interfaces { +namespace { + + class WalletImpl : public Wallet { + public: + WalletImpl(CWallet &wallet) : m_wallet(wallet) {} + + std::unique_ptr + handleShowProgress(ShowProgressFn fn) override { + return MakeHandler(m_wallet.ShowProgress.connect(fn)); + } + + CWallet &m_wallet; + }; + +} // namespace + +std::unique_ptr MakeWallet(CWallet &wallet) { + return std::make_unique(wallet); +} + +} // namespace interfaces diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -358,7 +358,7 @@ } void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle) { - SplashScreen *splash = new SplashScreen(0, networkStyle); + SplashScreen *splash = new SplashScreen(m_node, 0, networkStyle); // We don't hold a direct pointer to the splash screen after creation, but // the splash screen will take care of deleting itself when slotFinish // happens. diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h --- a/src/qt/splashscreen.h +++ b/src/qt/splashscreen.h @@ -8,9 +8,16 @@ #include #include -class CWallet; +#include + class NetworkStyle; +namespace interfaces { +class Handler; +class Node; +class Wallet; +}; + /** Class for the splashscreen with information of the running client. * * @note this is intentionally not a QSplashScreen. Bitcoin Core initialization @@ -21,7 +28,8 @@ Q_OBJECT public: - explicit SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle); + explicit SplashScreen(interfaces::Node &node, Qt::WindowFlags f, + const NetworkStyle *networkStyle); ~SplashScreen(); protected: @@ -45,14 +53,19 @@ /** Disconnect core signals to splash screen */ void unsubscribeFromCoreSignals(); /** Connect wallet signals to splash screen */ - void ConnectWallet(CWallet *); + void ConnectWallet(std::unique_ptr wallet); QPixmap pixmap; QString curMessage; QColor curColor; int curAlignment; - QList connectedWallets; + interfaces::Node &m_node; + std::unique_ptr m_handler_init_message; + std::unique_ptr m_handler_show_progress; + std::unique_ptr m_handler_load_wallet; + std::list> m_connected_wallets; + std::list> m_connected_wallet_handlers; }; #endif // BITCOIN_QT_SPLASHSCREEN_H diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -3,22 +3,21 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include #endif -#include "splashscreen.h" +#include -#include "networkstyle.h" +#include -#include "clientversion.h" -#include "init.h" -#include "ui_interface.h" -#include "util.h" -#include "version.h" - -#ifdef ENABLE_WALLET -#include "wallet/wallet.h" -#endif +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -26,8 +25,9 @@ #include #include -SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) - : QWidget(0, f), curAlignment(0) { +SplashScreen::SplashScreen(interfaces::Node &node, Qt::WindowFlags f, + const NetworkStyle *networkStyle) + : QWidget(0, f), curAlignment(0), m_node(node) { // set reference point, paddings int paddingRight = 50; int paddingTop = 50; @@ -158,7 +158,7 @@ if (ev->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast(ev); if (keyEvent->text()[0] == 'q') { - StartShutdown(); + m_node.startShutdown(); } } return QObject::eventFilter(obj, ev); @@ -189,37 +189,37 @@ : _("press q to shutdown")) + strprintf("\n%d", nProgress) + "%"); } - #ifdef ENABLE_WALLET -void SplashScreen::ConnectWallet(CWallet *wallet) { - wallet->ShowProgress.connect( - boost::bind(ShowProgress, this, _1, _2, false)); - connectedWallets.push_back(wallet); +void SplashScreen::ConnectWallet(std::unique_ptr wallet) { + m_connected_wallet_handlers.emplace_back(wallet->handleShowProgress( + boost::bind(ShowProgress, this, _1, _2, false))); + m_connected_wallets.emplace_back(std::move(wallet)); } #endif void SplashScreen::subscribeToCoreSignals() { // Connect signals to client - uiInterface.InitMessage.connect(boost::bind(InitMessage, this, _1)); - uiInterface.ShowProgress.connect( - boost::bind(ShowProgress, this, _1, _2, _3)); + m_handler_init_message = + m_node.handleInitMessage(boost::bind(InitMessage, this, _1)); + m_handler_show_progress = + m_node.handleShowProgress(boost::bind(ShowProgress, this, _1, _2, _3)); #ifdef ENABLE_WALLET - uiInterface.LoadWallet.connect( - boost::bind(&SplashScreen::ConnectWallet, this, _1)); + m_handler_load_wallet = m_node.handleLoadWallet( + [this](std::unique_ptr wallet) { + ConnectWallet(std::move(wallet)); + }); #endif } void SplashScreen::unsubscribeFromCoreSignals() { // Disconnect signals from client - uiInterface.InitMessage.disconnect(boost::bind(InitMessage, this, _1)); - uiInterface.ShowProgress.disconnect( - boost::bind(ShowProgress, this, _1, _2, _3)); -#ifdef ENABLE_WALLET - for (CWallet *const &pwallet : connectedWallets) { - pwallet->ShowProgress.disconnect( - boost::bind(ShowProgress, this, _1, _2, false)); + m_handler_init_message->disconnect(); + m_handler_show_progress->disconnect(); + for (auto &handler : m_connected_wallet_handlers) { + handler->disconnect(); } -#endif + m_connected_wallet_handlers.clear(); + m_connected_wallets.clear(); } void SplashScreen::showMessage(const QString &message, int alignment, @@ -240,6 +240,6 @@ void SplashScreen::closeEvent(QCloseEvent *event) { // allows an "emergency" shutdown during startup - StartShutdown(); + m_node.startShutdown(); event->ignore(); } diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt --- a/src/wallet/CMakeLists.txt +++ b/src/wallet/CMakeLists.txt @@ -10,6 +10,7 @@ find_package(Event REQUIRED) add_library(wallet + ../interfaces/wallet.cpp crypter.cpp db.cpp fees.cpp