aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am4
-rw-r--r--src/interface/handler.cpp33
-rw-r--r--src/interface/handler.h35
-rw-r--r--src/interface/node.cpp53
-rw-r--r--src/interface/node.h62
-rw-r--r--src/qt/bitcoin.cpp75
6 files changed, 215 insertions, 47 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 72e5cdb95d..affafaa5f9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -104,6 +104,8 @@ BITCOIN_CORE_H = \
httpserver.h \
indirectmap.h \
init.h \
+ interface/handler.h \
+ interface/node.h \
key.h \
key_io.h \
keystore.h \
@@ -357,6 +359,8 @@ libbitcoin_util_a_SOURCES = \
compat/glibcxx_sanity.cpp \
compat/strnlen.cpp \
fs.cpp \
+ interface/handler.cpp \
+ interface/node.cpp \
random.cpp \
rpc/protocol.cpp \
rpc/util.cpp \
diff --git a/src/interface/handler.cpp b/src/interface/handler.cpp
new file mode 100644
index 0000000000..4b27f374f4
--- /dev/null
+++ b/src/interface/handler.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 <interface/handler.h>
+
+#include <util.h>
+
+#include <boost/signals2/connection.hpp>
+#include <memory>
+#include <utility>
+
+namespace interface {
+namespace {
+
+class HandlerImpl : public Handler
+{
+public:
+ HandlerImpl(boost::signals2::connection connection) : m_connection(std::move(connection)) {}
+
+ void disconnect() override { m_connection.disconnect(); }
+
+ boost::signals2::scoped_connection m_connection;
+};
+
+} // namespace
+
+std::unique_ptr<Handler> MakeHandler(boost::signals2::connection connection)
+{
+ return MakeUnique<HandlerImpl>(std::move(connection));
+}
+
+} // namespace interface
diff --git a/src/interface/handler.h b/src/interface/handler.h
new file mode 100644
index 0000000000..a76334bfbf
--- /dev/null
+++ b/src/interface/handler.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_INTERFACE_HANDLER_H
+#define BITCOIN_INTERFACE_HANDLER_H
+
+#include <memory>
+
+namespace boost {
+namespace signals2 {
+class connection;
+} // namespace signals2
+} // namespace boost
+
+namespace interface {
+
+//! Generic interface for managing an event handler or callback function
+//! registered with another interface. Has a single disconnect method to cancel
+//! the registration and prevent any future notifications.
+class Handler
+{
+public:
+ virtual ~Handler() {}
+
+ //! Disconnect the handler.
+ virtual void disconnect() = 0;
+};
+
+//! Return handler wrapping a boost signal connection.
+std::unique_ptr<Handler> MakeHandler(boost::signals2::connection connection);
+
+} // namespace interface
+
+#endif // BITCOIN_INTERFACE_HANDLER_H
diff --git a/src/interface/node.cpp b/src/interface/node.cpp
new file mode 100644
index 0000000000..4e3fa6ceb9
--- /dev/null
+++ b/src/interface/node.cpp
@@ -0,0 +1,53 @@
+// 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 <interface/node.h>
+
+#include <chainparams.h>
+#include <init.h>
+#include <interface/handler.h>
+#include <scheduler.h>
+#include <ui_interface.h>
+#include <util.h>
+#include <warnings.h>
+
+#include <boost/thread/thread.hpp>
+
+namespace interface {
+namespace {
+
+class NodeImpl : public Node
+{
+ void parseParameters(int argc, const char* const argv[]) override
+ {
+ gArgs.ParseParameters(argc, argv);
+ }
+ void readConfigFile(const std::string& conf_path) override { gArgs.ReadConfigFile(conf_path); }
+ void selectParams(const std::string& network) override { SelectParams(network); }
+ void initLogging() override { InitLogging(); }
+ void initParameterInteraction() override { InitParameterInteraction(); }
+ std::string getWarnings(const std::string& type) override { return GetWarnings(type); }
+ bool baseInitialize() override
+ {
+ return AppInitBasicSetup() && AppInitParameterInteraction() && AppInitSanityChecks() &&
+ AppInitLockDataDirectory();
+ }
+ bool appInitMain() override { return AppInitMain(); }
+ void appShutdown() override
+ {
+ Interrupt();
+ Shutdown();
+ }
+ void startShutdown() override { StartShutdown(); }
+ std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override
+ {
+ return MakeHandler(::uiInterface.InitMessage.connect(fn));
+ }
+};
+
+} // namespace
+
+std::unique_ptr<Node> MakeNode() { return MakeUnique<NodeImpl>(); }
+
+} // namespace interface
diff --git a/src/interface/node.h b/src/interface/node.h
new file mode 100644
index 0000000000..b69ef160a3
--- /dev/null
+++ b/src/interface/node.h
@@ -0,0 +1,62 @@
+// 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_INTERFACE_NODE_H
+#define BITCOIN_INTERFACE_NODE_H
+
+#include <functional>
+#include <memory>
+#include <string>
+
+namespace interface {
+
+class Handler;
+
+//! Top-level interface for a bitcoin node (bitcoind process).
+class Node
+{
+public:
+ virtual ~Node() {}
+
+ //! Set command line arguments.
+ virtual void parseParameters(int argc, const char* const argv[]) = 0;
+
+ //! Load settings from configuration file.
+ virtual void readConfigFile(const std::string& conf_path) = 0;
+
+ //! Choose network parameters.
+ virtual void selectParams(const std::string& network) = 0;
+
+ //! Init logging.
+ virtual void initLogging() = 0;
+
+ //! Init parameter interaction.
+ virtual void initParameterInteraction() = 0;
+
+ //! Get warnings.
+ virtual std::string getWarnings(const std::string& type) = 0;
+
+ //! Initialize app dependencies.
+ virtual bool baseInitialize() = 0;
+
+ //! Start node.
+ virtual bool appInitMain() = 0;
+
+ //! Stop node.
+ virtual void appShutdown() = 0;
+
+ //! Start shutdown.
+ virtual void startShutdown() = 0;
+
+ //! Register handler for init messages.
+ using InitMessageFn = std::function<void(const std::string& message)>;
+ virtual std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) = 0;
+};
+
+//! Return implementation of Node interface.
+std::unique_ptr<Node> MakeNode();
+
+} // namespace interface
+
+#endif // BITCOIN_INTERFACE_NODE_H
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 140e56123f..4ab5a891e3 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -27,6 +27,8 @@
#endif
#include <init.h>
+#include <interface/handler.h>
+#include <interface/node.h>
#include <rpc/server.h>
#include <ui_interface.h>
#include <uint256.h>
@@ -180,11 +182,7 @@ class BitcoinCore: public QObject
{
Q_OBJECT
public:
- explicit BitcoinCore();
- /** Basic initialization, before starting initialization/shutdown thread.
- * Return true on success.
- */
- static bool baseInitialize();
+ explicit BitcoinCore(interface::Node& node);
public Q_SLOTS:
void initialize();
@@ -196,9 +194,10 @@ Q_SIGNALS:
void runawayException(const QString &message);
private:
-
/// Pass fatal exception message to UI thread
void handleRunawayException(const std::exception *e);
+
+ interface::Node& m_node;
};
/** Main Bitcoin application object */
@@ -206,7 +205,7 @@ class BitcoinApplication: public QApplication
{
Q_OBJECT
public:
- explicit BitcoinApplication(int &argc, char **argv);
+ explicit BitcoinApplication(interface::Node& node, int &argc, char **argv);
~BitcoinApplication();
#ifdef ENABLE_WALLET
@@ -247,6 +246,7 @@ Q_SIGNALS:
private:
QThread *coreThread;
+ interface::Node& m_node;
OptionsModel *optionsModel;
ClientModel *clientModel;
BitcoinGUI *window;
@@ -264,36 +264,15 @@ private:
#include <qt/bitcoin.moc>
-BitcoinCore::BitcoinCore():
- QObject()
+BitcoinCore::BitcoinCore(interface::Node& node) :
+ QObject(), m_node(node)
{
}
void BitcoinCore::handleRunawayException(const std::exception *e)
{
PrintExceptionContinue(e, "Runaway exception");
- Q_EMIT runawayException(QString::fromStdString(GetWarnings("gui")));
-}
-
-bool BitcoinCore::baseInitialize()
-{
- if (!AppInitBasicSetup())
- {
- return false;
- }
- if (!AppInitParameterInteraction())
- {
- return false;
- }
- if (!AppInitSanityChecks())
- {
- return false;
- }
- if (!AppInitLockDataDirectory())
- {
- return false;
- }
- return true;
+ Q_EMIT runawayException(QString::fromStdString(m_node.getWarnings("gui")));
}
void BitcoinCore::initialize()
@@ -301,7 +280,7 @@ void BitcoinCore::initialize()
try
{
qDebug() << __func__ << ": Running initialization in thread";
- bool rv = AppInitMain();
+ bool rv = m_node.appInitMain();
Q_EMIT initializeResult(rv);
} catch (const std::exception& e) {
handleRunawayException(&e);
@@ -315,8 +294,7 @@ void BitcoinCore::shutdown()
try
{
qDebug() << __func__ << ": Running Shutdown in thread";
- Interrupt();
- Shutdown();
+ m_node.appShutdown();
qDebug() << __func__ << ": Shutdown finished";
Q_EMIT shutdownResult();
} catch (const std::exception& e) {
@@ -326,9 +304,10 @@ void BitcoinCore::shutdown()
}
}
-BitcoinApplication::BitcoinApplication(int &argc, char **argv):
+BitcoinApplication::BitcoinApplication(interface::Node& node, int &argc, char **argv):
QApplication(argc, argv),
coreThread(0),
+ m_node(node),
optionsModel(0),
clientModel(0),
window(0),
@@ -409,7 +388,7 @@ void BitcoinApplication::startThread()
if(coreThread)
return;
coreThread = new QThread(this);
- BitcoinCore *executor = new BitcoinCore();
+ BitcoinCore *executor = new BitcoinCore(m_node);
executor->moveToThread(coreThread);
/* communication to and from thread */
@@ -427,8 +406,8 @@ void BitcoinApplication::startThread()
void BitcoinApplication::parameterSetup()
{
- InitLogging();
- InitParameterInteraction();
+ m_node.initLogging();
+ m_node.initParameterInteraction();
}
void BitcoinApplication::requestInitialize()
@@ -461,7 +440,7 @@ void BitcoinApplication::requestShutdown()
delete clientModel;
clientModel = 0;
- StartShutdown();
+ m_node.startShutdown();
// Request shutdown from core thread
Q_EMIT requestedShutdown();
@@ -555,9 +534,11 @@ int main(int argc, char *argv[])
{
SetupEnvironment();
+ std::unique_ptr<interface::Node> node = interface::MakeNode();
+
/// 1. Parse command-line options. These take precedence over anything else.
// Command-line options take precedence:
- gArgs.ParseParameters(argc, argv);
+ node->parseParameters(argc, argv);
// Do not refer to data directory yet, this can be overridden by Intro::pickDataDirectory
@@ -571,7 +552,7 @@ int main(int argc, char *argv[])
Q_INIT_RESOURCE(bitcoin);
Q_INIT_RESOURCE(bitcoin_locale);
- BitcoinApplication app(argc, argv);
+ BitcoinApplication app(*node, argc, argv);
#if QT_VERSION > 0x050100
// Generate high-dpi pixmaps
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
@@ -633,7 +614,7 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
try {
- gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
+ node->readConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
} catch (const std::exception& e) {
QMessageBox::critical(0, QObject::tr(PACKAGE_NAME),
QObject::tr("Error: Cannot parse configuration file: %1. Only use key=value syntax.").arg(e.what()));
@@ -648,7 +629,7 @@ int main(int argc, char *argv[])
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
try {
- SelectParams(ChainNameFromCommandLine());
+ node->selectParams(ChainNameFromCommandLine());
} catch(std::exception &e) {
QMessageBox::critical(0, QObject::tr(PACKAGE_NAME), QObject::tr("Error: %1").arg(e.what()));
return EXIT_FAILURE;
@@ -705,7 +686,7 @@ int main(int argc, char *argv[])
app.createOptionsModel(gArgs.GetBoolArg("-resetguisettings", false));
// Subscribe to global signals from core
- uiInterface.InitMessage.connect(InitMessage);
+ std::unique_ptr<interface::Handler> handler = node->handleInitMessage(InitMessage);
if (gArgs.GetBoolArg("-splash", DEFAULT_SPLASHSCREEN) && !gArgs.GetBoolArg("-min", false))
app.createSplashScreen(networkStyle.data());
@@ -717,7 +698,7 @@ int main(int argc, char *argv[])
// Perform base initialization before spinning up initialization/shutdown thread
// This is acceptable because this function only contains steps that are quick to execute,
// so the GUI thread won't be held up.
- if (BitcoinCore::baseInitialize()) {
+ if (node->baseInitialize()) {
app.requestInitialize();
#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("%1 didn't yet exit safely...").arg(QObject::tr(PACKAGE_NAME)), (HWND)app.getMainWinId());
@@ -732,10 +713,10 @@ int main(int argc, char *argv[])
}
} catch (const std::exception& e) {
PrintExceptionContinue(&e, "Runaway exception");
- app.handleRunawayException(QString::fromStdString(GetWarnings("gui")));
+ app.handleRunawayException(QString::fromStdString(node->getWarnings("gui")));
} catch (...) {
PrintExceptionContinue(nullptr, "Runaway exception");
- app.handleRunawayException(QString::fromStdString(GetWarnings("gui")));
+ app.handleRunawayException(QString::fromStdString(node->getWarnings("gui")));
}
return rv;
}