diff --git a/CMakeLists.txt b/CMakeLists.txt index 00de5c2a9128..931aebf4b275 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -194,7 +194,8 @@ set(SERVER_SOURCES ./src/httprpc.cpp ./src/httpserver.cpp ./src/init.cpp - ./src/interface/wallet.cpp + ./src/interfaces/handler.cpp + ./src/interfaces/wallet.cpp ./src/dbwrapper.cpp ./src/legacy/validation_zerocoin_legacy.cpp ./src/merkleblock.cpp diff --git a/src/Makefile.am b/src/Makefile.am index edc4f1a6e97f..986fd6cd8a68 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -190,7 +190,8 @@ BITCOIN_CORE_H = \ httprpc.h \ httpserver.h \ init.h \ - interface/wallet.h \ + interfaces/handler.h \ + interfaces/wallet.h \ invalid.h \ invalid_outpoints.json.h \ invalid_serials.json.h \ @@ -373,7 +374,7 @@ libbitcoin_wallet_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_wallet_a_SOURCES = \ activemasternode.cpp \ bip38.cpp \ - interface/wallet.cpp \ + interfaces/wallet.cpp \ addressbook.cpp \ crypter.cpp \ key_io.cpp \ @@ -533,6 +534,7 @@ libbitcoin_util_a_SOURCES = \ compat/glibcxx_sanity.cpp \ compat/strnlen.cpp \ fs.cpp \ + interfaces/handler.cpp \ logging.cpp \ random.cpp \ rpc/protocol.cpp \ diff --git a/src/init.cpp b/src/init.cpp index 7604cc1e6f68..ae4d380d4101 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -232,7 +232,10 @@ void PrepareShutdown() #endif StopMapPort(); - UnregisterValidationInterface(peerLogic.get()); + // Because these depend on each-other, we make sure that neither can be + // using the other before destroying them. + if (peerLogic) UnregisterValidationInterface(peerLogic.get()); + if (g_connman) g_connman->Stop(); peerLogic.reset(); g_connman.reset(); @@ -776,6 +779,18 @@ bool AppInitServers() std::terminate(); }; +namespace { // Variables internal to initialization process only + + ServiceFlags nRelevantServices = NODE_NETWORK; + int nMaxConnections; + int nUserMaxConnections; + int nFD; + ServiceFlags nLocalServices = NODE_NETWORK; + + std::string strWalletFile; + bool fDisableWallet = false; +} + bool AppInitBasicSetup() { // ********************************************************* Step 1: setup @@ -969,16 +984,10 @@ void InitLogging() LogPrintf("PIVX version %s (%s)\n", version_string, CLIENT_DATE); } -/** Initialize pivx. - * @pre Parameters should be parsed and config file should be read. - */ -bool AppInit2() +bool AppInitParameterInteraction() { - // ********************************************************* Step 1: setup - if (!AppInitBasicSetup()) - return false; - // ********************************************************* Step 2: parameter interactions + // Make sure enough file descriptors are available // -bind and -whitebind can't be set when not listening @@ -988,12 +997,12 @@ bool AppInit2() } int nBind = std::max(nUserBind, size_t(1)); - int nUserMaxConnections = gArgs.GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS); - int nMaxConnections = std::max(nUserMaxConnections, 0); + nUserMaxConnections = gArgs.GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS); + nMaxConnections = std::max(nUserMaxConnections, 0); // Trim requested connection counts, to fit into system limitations - nMaxConnections = std::max(std::min(nMaxConnections, (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0); - int nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS); + nMaxConnections = std::max(std::min(nMaxConnections, (int) (FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0); + nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS); if (nFD < MIN_CORE_FILEDESCRIPTORS) return UIError(_("Not enough file descriptors available.")); if (nFD - MIN_CORE_FILEDESCRIPTORS < nMaxConnections) @@ -1005,7 +1014,7 @@ bool AppInit2() const std::vector& categories = gArgs.GetArgs("-debug"); if (!(gArgs.GetBoolArg("-nodebug", false) || - find(categories.begin(), categories.end(), std::string("0")) != categories.end())) { + find(categories.begin(), categories.end(), std::string("0")) != categories.end())) { for (const auto& cat : categories) { if (!g_logger->EnableCategory(cat)) { UIWarning(strprintf(_("Unsupported logging category %s=%s."), "-debug", cat)); @@ -1025,7 +1034,8 @@ bool AppInit2() UIWarning(_("Warning: Unsupported argument -debugnet ignored, use -debug=net.")); // Check for -socks - as this is a privacy risk to continue, exit here if (gArgs.IsArgSet("-socks")) - return UIError(_("Error: Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.")); + return UIError( + _("Error: Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.")); // Check for -tor - as this is a privacy risk to continue, exit here if (gArgs.GetBoolArg("-tor", false)) return UIError(_("Error: Unsupported argument -tor found, use -onion.")); @@ -1039,7 +1049,8 @@ bool AppInit2() UIWarning(_("Warning: Unsupported argument -benchmark ignored, use -debug=bench.")); // Checkmempool and checkblockindex default to true in regtest mode - int ratio = std::min(std::max(gArgs.GetArg("-checkmempool", Params().DefaultConsistencyChecks() ? 1 : 0), 0), 1000000); + int ratio = std::min( + std::max(gArgs.GetArg("-checkmempool", Params().DefaultConsistencyChecks() ? 1 : 0), 0), 1000000); if (ratio != 0) { mempool.setSanityCheck(1.0 / ratio); } @@ -1050,7 +1061,8 @@ bool AppInit2() int64_t nMempoolSizeLimit = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; int64_t nMempoolDescendantSizeLimit = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000; if (nMempoolSizeLimit < 0 || nMempoolSizeLimit < nMempoolDescendantSizeLimit * 40) - return UIError(strprintf(_("Error: -maxmempool must be at least %d MB"), gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) / 25)); + return UIError(strprintf(_("Error: -maxmempool must be at least %d MB"), + gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) / 25)); // -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency nScriptCheckThreads = gArgs.GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS); @@ -1097,7 +1109,7 @@ bool AppInit2() } #ifdef ENABLE_WALLET - std::string strWalletFile = gArgs.GetArg("-wallet", DEFAULT_WALLET_DAT); + strWalletFile = gArgs.GetArg("-wallet", DEFAULT_WALLET_DAT); if (!CWallet::ParameterInteraction()) return false; #endif // ENABLE_WALLET @@ -1110,9 +1122,6 @@ bool AppInit2() SetMockTime(gArgs.GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op } - ServiceFlags nLocalServices = NODE_NETWORK; - ServiceFlags nRelevantServices = NODE_NETWORK; - if (gArgs.GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS)) nLocalServices = ServiceFlags(nLocalServices | NODE_BLOOM); @@ -1121,7 +1130,39 @@ bool AppInit2() if (!InitNUParams()) return false; - // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log + return true; +} + +static bool LockDataDirectory(bool probeOnly) +{ + std::string strDataDir = GetDataDir().string(); + + // Make sure only a single PIVX process is using the data directory. + fs::path pathLockFile = GetDataDir() / ".lock"; + FILE* file = fsbridge::fopen(pathLockFile, "a"); // empty lock file; created if it doesn't exist. + if (file) fclose(file); + + try { + static boost::interprocess::file_lock lock(pathLockFile.string().c_str()); + // Wait maximum 10 seconds if an old wallet is still running. Avoids lockup during restart + if (!lock.timed_lock(boost::get_system_time() + boost::posix_time::seconds(10))) { + return UIError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."), + strDataDir, _(PACKAGE_NAME))); + } + if (probeOnly) { + lock.unlock(); + } + } catch (const boost::interprocess::interprocess_exception& e) { + return UIError( + strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running.") + " %s.", + strDataDir, _(PACKAGE_NAME), e.what())); + } + return true; +} + +bool AppInitSanityChecks() +{ + // ********************************************************* Step 4: sanity checks // Initialize elliptic curve code RandomInit(); @@ -1130,19 +1171,22 @@ bool AppInit2() // Sanity check if (!InitSanityCheck()) - return UIError(_("Initialization sanity check failed. PIVX Core is shutting down.")); + return UIError(strprintf(_("Initialization sanity check failed. %s is shutting down."), _(PACKAGE_NAME))); - std::string strDataDir = GetDataDir().string(); - - // Make sure only a single PIVX process is using the data directory. - fs::path pathLockFile = GetDataDir() / ".lock"; - FILE* file = fsbridge::fopen(pathLockFile, "a"); // empty lock file; created if it doesn't exist. - if (file) fclose(file); - static boost::interprocess::file_lock lock(pathLockFile.string().c_str()); + // Probe the data directory lock to give an early error message, if possible + return LockDataDirectory(true); +} - // Wait maximum 10 seconds if an old wallet is still running. Avoids lockup during restart - if (!lock.timed_lock(boost::get_system_time() + boost::posix_time::seconds(10))) - return UIError(strprintf(_("Cannot obtain a lock on data directory %s. PIVX Core is probably already running."), strDataDir)); +bool AppInitMain() +{ + // ********************************************************* Step 4a: application initialization + // After daemonization get the data directory lock again and hold on to it until exit + // This creates a slight window for a race condition to happen, however this condition is harmless: it + // will at most make us exit without printing a message to console. + if (!LockDataDirectory(false)) { + // Detailed error printed inside LockDataDirectory + return false; + } #ifndef WIN32 CreatePidFile(GetPidFile(), getpid()); @@ -1159,7 +1203,7 @@ bool AppInit2() if (!g_logger->m_log_timestamps) LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime())); LogPrintf("Default data directory %s\n", GetDefaultDataDir().string()); - LogPrintf("Using data directory %s\n", strDataDir); + LogPrintf("Using data directory %s\n", GetDataDir().string()); LogPrintf("Using config file %s\n", GetConfigFile().string()); LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD); std::ostringstream strErrors; @@ -1179,8 +1223,8 @@ bool AppInit2() } // Start the lightweight task scheduler thread - CScheduler::Function serviceLoop = boost::bind(&CScheduler::serviceQueue, &scheduler); - threadGroup.create_thread(boost::bind(&TraceThread, "scheduler", serviceLoop)); + CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler); + threadGroup.create_thread(std::bind(&TraceThread, "scheduler", serviceLoop)); // Initialize Sapling circuit parameters LoadSaplingParams(); @@ -1688,7 +1732,7 @@ bool AppInit2() for (const std::string& strFile : gArgs.GetArgs("-loadblock")) { vImportFiles.push_back(strFile);; } - threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles)); + threadGroup.create_thread(std::bind(&ThreadImport, vImportFiles)); // Wait for genesis block to be processed LogPrintf("Waiting for genesis block to be imported...\n"); @@ -1797,7 +1841,7 @@ bool AppInit2() LogPrintf("fLiteMode %d\n", fLiteMode); LogPrintf("Budget Mode %s\n", strBudgetMode.c_str()); - threadGroup.create_thread(boost::bind(&ThreadCheckMasternodes)); + threadGroup.create_thread(std::bind(&ThreadCheckMasternodes)); if (ShutdownRequested()) { LogPrintf("Shutdown requested. Exiting.\n"); @@ -1865,7 +1909,7 @@ bool AppInit2() // StakeMiner thread disabled by default on regtest if (gArgs.GetBoolArg("-staking", !Params().IsRegTestNet() && DEFAULT_STAKING)) { - threadGroup.create_thread(boost::bind(&ThreadStakeMinter)); + threadGroup.create_thread(std::bind(&ThreadStakeMinter)); } } #endif diff --git a/src/init.h b/src/init.h index 65f4dbd742c7..2af4673eb84b 100644 --- a/src/init.h +++ b/src/init.h @@ -27,13 +27,30 @@ void PrepareShutdown(); void InitLogging(); //!Parameter interaction: change current parameters depending on various rules void InitParameterInteraction(); -bool AppInit2(); /** Initialize PIVX core: Basic context setup. * @note This can be done before daemonization. Do not call Shutdown() if this function fails. * @pre Parameters should be parsed and config file should be read. */ bool AppInitBasicSetup(); +/** + * Initialization: parameter interaction. + * @note This can be done before daemonization. + * @pre Parameters should be parsed and config file should be read, AppInitBasicSetup should have been called. + */ +bool AppInitParameterInteraction(); +/** + * Initialization sanity checks: ecc init, sanity checks, dir lock. + * @note This can be done before daemonization. + * @pre Parameters should be parsed and config file should be read, AppInitParameterInteraction should have been called. + */ +bool AppInitSanityChecks(); +/** + * Bitcoin core main initialization. + * @note This should only be done after daemonization. + * @pre Parameters should be parsed and config file should be read, AppInitSanityChecks should have been called. + */ +bool AppInitMain(); /** The help message mode determines what help message to show */ enum HelpMessageMode { diff --git a/src/interfaces/handler.cpp b/src/interfaces/handler.cpp new file mode 100644 index 000000000000..c2e33080f87b --- /dev/null +++ b/src/interfaces/handler.cpp @@ -0,0 +1,33 @@ +// Copyright (c) 2018-2020 The Bitcoin Core developers +// Copyright (c) 2020 The PIVX Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php. + +#include + +#include + +#include +#include + +namespace interfaces { +namespace { + +class HandlerImpl : public Handler +{ +public: + explicit 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 MakeHandler(boost::signals2::connection connection) +{ + return MakeUnique(std::move(connection)); +} + +} // namespace interfaces diff --git a/src/interfaces/handler.h b/src/interfaces/handler.h new file mode 100644 index 000000000000..b15d06c39315 --- /dev/null +++ b/src/interfaces/handler.h @@ -0,0 +1,36 @@ +// Copyright (c) 2018-2020 The Bitcoin Core developers +// Copyright (c) 2020 The PIVX Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php. + +#ifndef PIVX_INTERFACES_HANDLER_H +#define PIVX_INTERFACES_HANDLER_H + +#include + +namespace boost { +namespace signals2 { +class connection; +} // namespace signals2 +} // namespace boost + +namespace interfaces { + +//! 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 MakeHandler(boost::signals2::connection connection); + +} // namespace interfaces + +#endif // PIVX_INTERFACES_HANDLER_H diff --git a/src/interface/wallet.cpp b/src/interfaces/wallet.cpp similarity index 97% rename from src/interface/wallet.cpp rename to src/interfaces/wallet.cpp index ff7d0c2e0efe..9f67ba079ba7 100644 --- a/src/interface/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -3,7 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or https://www.opensource.org/licenses/mit-license.php. -#include "interface/wallet.h" +#include "interfaces/wallet.h" #include "wallet.h" namespace interfaces { diff --git a/src/interface/wallet.h b/src/interfaces/wallet.h similarity index 100% rename from src/interface/wallet.h rename to src/interfaces/wallet.h diff --git a/src/miner.cpp b/src/miner.cpp index c3ae0a0ebfb7..650541bb4fc9 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -746,7 +746,7 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads) minerThreads = new boost::thread_group(); for (int i = 0; i < nThreads; i++) - minerThreads->create_thread(boost::bind(&ThreadBitcoinMiner, pwallet)); + minerThreads->create_thread(std::bind(&ThreadBitcoinMiner, pwallet)); } // ppcoin: stake minter thread diff --git a/src/net.cpp b/src/net.cpp index 277559bc1cfa..9505f2d7476b 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2180,7 +2180,7 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c threadMessageHandler = std::thread(&TraceThread >, "msghand", std::function(std::bind(&CConnman::ThreadMessageHandler, this))); // Dump network addresses - scheduler.scheduleEvery(boost::bind(&CConnman::DumpData, this), DUMP_ADDRESSES_INTERVAL); + scheduler.scheduleEvery(std::bind(&CConnman::DumpData, this), DUMP_ADDRESSES_INTERVAL); return true; } diff --git a/src/pivxd.cpp b/src/pivxd.cpp index e864228ef037..d7d057a4d4b8 100644 --- a/src/pivxd.cpp +++ b/src/pivxd.cpp @@ -108,6 +108,24 @@ bool AppInit(int argc, char* argv[]) } } + // -server defaults to true for bitcoind but not for the GUI so do this here + gArgs.SoftSetBoolArg("-server", true); + // Set this early so that parameter interactions go to console + InitLogging(); + InitParameterInteraction(); + if (!AppInitBasicSetup()) { + // UIError will have been called with detailed error, which ends up on console + exit(1); + } + if (!AppInitParameterInteraction()) { + // UIError will have been called with detailed error, which ends up on console + exit(1); + } + if (!AppInitSanityChecks()) { + // UIError will have been called with detailed error, which ends up on console + exit(1); + } + #ifndef WIN32 fDaemon = gArgs.GetBoolArg("-daemon", false); if (fDaemon) { @@ -130,12 +148,9 @@ bool AppInit(int argc, char* argv[]) fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno); } #endif - gArgs.SoftSetBoolArg("-server", true); // Set this early so that parameter interactions go to console - InitLogging(); - InitParameterInteraction(); - fRet = AppInit2(); + fRet = AppInitMain(); } catch (const std::exception& e) { PrintExceptionContinue(&e, "AppInit()"); } catch (...) { diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 699a004ed5f6..18559865bac1 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -14,7 +14,7 @@ #include "chainparams.h" #include "checkpoints.h" #include "clientversion.h" -#include "masternode-sync.h" +#include "interfaces/handler.h" #include "masternodeman.h" #include "net.h" #include "netbase.h" @@ -310,21 +310,21 @@ static void BannedListChanged(ClientModel *clientmodel) void ClientModel::subscribeToCoreSignals() { // Connect signals to client - uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2)); - uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1)); - uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this)); - uiInterface.BannedListChanged.connect(boost::bind(BannedListChanged, this)); - uiInterface.NotifyBlockTip.connect(boost::bind(BlockTipChanged, this, _1, _2)); + m_handler_show_progress = interfaces::MakeHandler(uiInterface.ShowProgress.connect(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2))); + m_handler_notify_num_connections_changed = interfaces::MakeHandler(uiInterface.NotifyNumConnectionsChanged.connect(std::bind(NotifyNumConnectionsChanged, this, std::placeholders::_1))); + m_handler_notify_alert_changed = interfaces::MakeHandler(uiInterface.NotifyAlertChanged.connect(std::bind(NotifyAlertChanged, this))); + m_handler_banned_list_changed = interfaces::MakeHandler(uiInterface.BannedListChanged.connect(std::bind(BannedListChanged, this))); + m_handler_notify_block_tip = interfaces::MakeHandler(uiInterface.NotifyBlockTip.connect(std::bind(BlockTipChanged, this, std::placeholders::_1, std::placeholders::_2))); } void ClientModel::unsubscribeFromCoreSignals() { // Disconnect signals from client - uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); - uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1)); - uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this)); - uiInterface.BannedListChanged.disconnect(boost::bind(BannedListChanged, this)); - uiInterface.NotifyBlockTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2)); + m_handler_show_progress->disconnect(); + m_handler_notify_num_connections_changed->disconnect(); + m_handler_notify_alert_changed->disconnect(); + m_handler_banned_list_changed->disconnect(); + m_handler_notify_block_tip->disconnect(); } bool ClientModel::getTorInfo(std::string& ip_port) const diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index cc495f65b6ce..e2284aaf04bd 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -12,13 +12,17 @@ #include #include +#include + class AddressTableModel; class BanTableModel; class OptionsModel; class PeerTableModel; class TransactionTableModel; -class CWallet; +namespace interfaces { + class Handler; +} QT_BEGIN_NAMESPACE class QDateTime; @@ -94,6 +98,13 @@ class ClientModel : public QObject QString getMasternodesCount(); private: + // Listeners + std::unique_ptr m_handler_show_progress; + std::unique_ptr m_handler_notify_num_connections_changed; + std::unique_ptr m_handler_notify_alert_changed; + std::unique_ptr m_handler_banned_list_changed; + std::unique_ptr m_handler_notify_block_tip; + QString getMasternodeCountString() const; OptionsModel* optionsModel; PeerTableModel* peerTableModel; diff --git a/src/qt/pivx.cpp b/src/qt/pivx.cpp index bb0c07decb0e..ef99ca8bcc8f 100644 --- a/src/qt/pivx.cpp +++ b/src/qt/pivx.cpp @@ -257,7 +257,19 @@ void BitcoinCore::initialize() try { qDebug() << __func__ << ": Running AppInit2 in thread"; - int rv = AppInit2(); + if (!AppInitBasicSetup()) { + Q_EMIT initializeResult(false); + return; + } + if (!AppInitParameterInteraction()) { + Q_EMIT initializeResult(false); + return; + } + if (!AppInitSanityChecks()) { + Q_EMIT initializeResult(false); + return; + } + int rv = AppInitMain(); Q_EMIT initializeResult(rv); } catch (const std::exception& e) { handleRunawayException(&e); diff --git a/src/qt/pivx/pivxgui.cpp b/src/qt/pivx/pivxgui.cpp index 08b79a36f64a..c8800cb60045 100644 --- a/src/qt/pivx/pivxgui.cpp +++ b/src/qt/pivx/pivxgui.cpp @@ -10,6 +10,7 @@ #include "qt/guiutil.h" #include "clientmodel.h" +#include "interfaces/handler.h" #include "optionsmodel.h" #include "networkstyle.h" #include "notificator.h" @@ -689,11 +690,11 @@ static bool ThreadSafeMessageBox(PIVXGUI* gui, const std::string& message, const void PIVXGUI::subscribeToCoreSignals() { // Connect signals to client - uiInterface.ThreadSafeMessageBox.connect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3)); + m_handler_message_box = interfaces::MakeHandler(uiInterface.ThreadSafeMessageBox.connect(std::bind(ThreadSafeMessageBox, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3))); } void PIVXGUI::unsubscribeFromCoreSignals() { // Disconnect signals from client - uiInterface.ThreadSafeMessageBox.disconnect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3)); + m_handler_message_box->disconnect(); } diff --git a/src/qt/pivx/pivxgui.h b/src/qt/pivx/pivxgui.h index 148fbd0830bb..e343e9030c6a 100644 --- a/src/qt/pivx/pivxgui.h +++ b/src/qt/pivx/pivxgui.h @@ -27,6 +27,9 @@ #include "qt/pivx/settings/settingsfaqwidget.h" #include "qt/rpcconsole.h" +namespace interfaces { + class Handler; +} class ClientModel; class NetworkStyle; @@ -114,6 +117,9 @@ public Q_SLOTS: */ private: + // Handlers + std::unique_ptr m_handler_message_box; + bool enableWallet; ClientModel* clientModel = nullptr; @@ -121,7 +127,6 @@ public Q_SLOTS: QAction* quitAction = nullptr; QAction* toggleHideAction = nullptr; - // Frame NavMenuWidget *navMenu = nullptr; TopBar *topBar = nullptr; diff --git a/src/qt/pivx/splash.cpp b/src/qt/pivx/splash.cpp index 9a91fb2aa6ab..eca2c3bc8c18 100644 --- a/src/qt/pivx/splash.cpp +++ b/src/qt/pivx/splash.cpp @@ -6,6 +6,7 @@ #include "qt/pivx/forms/ui_splash.h" #include "QFile" +#include "interfaces/handler.h" #include "init.h" #include "guiinterface.h" #include "networkstyle.h" @@ -76,27 +77,30 @@ static void ShowProgress(Splash* splash, const std::string& title, int nProgress } #ifdef ENABLE_WALLET +std::unique_ptr m_handler_show_progress_wallet; static void ConnectWallet(Splash* splash, CWallet* wallet){ - wallet->ShowProgress.connect(boost::bind(ShowProgress, splash, _1, _2)); + m_handler_show_progress_wallet = interfaces::MakeHandler(wallet->ShowProgress.connect(std::bind(ShowProgress, splash, std::placeholders::_1, std::placeholders::_2))); } #endif void Splash::subscribeToCoreSignals(){ // Connect signals to client - uiInterface.InitMessage.connect(boost::bind(InitMessage, this, _1)); - uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2)); + m_handler_init_message = interfaces::MakeHandler(uiInterface.InitMessage.connect(std::bind(InitMessage, this, std::placeholders::_1))); + m_handler_show_progress = interfaces::MakeHandler(uiInterface.ShowProgress.connect(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2))); #ifdef ENABLE_WALLET - uiInterface.LoadWallet.connect(boost::bind(ConnectWallet, this, _1)); + m_handler_load_wallet = interfaces::MakeHandler(uiInterface.LoadWallet.connect(std::bind(ConnectWallet, this, std::placeholders::_1))); #endif } void Splash::unsubscribeFromCoreSignals(){ // Disconnect signals from client - uiInterface.InitMessage.disconnect(boost::bind(InitMessage, this, _1)); - uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); + m_handler_init_message->disconnect(); + m_handler_show_progress->disconnect(); #ifdef ENABLE_WALLET - if (pwalletMain) - pwalletMain->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); + if (pwalletMain) { + m_handler_load_wallet->disconnect(); + if (m_handler_show_progress_wallet) m_handler_show_progress_wallet->disconnect(); + } #endif } diff --git a/src/qt/pivx/splash.h b/src/qt/pivx/splash.h index b6db30427e5a..cc6a667a36ed 100644 --- a/src/qt/pivx/splash.h +++ b/src/qt/pivx/splash.h @@ -7,8 +7,14 @@ #include +#include + class NetworkStyle; +namespace interfaces { + class Handler; +}; + namespace Ui { class Splash; } @@ -34,6 +40,11 @@ public Q_SLOTS: private: Ui::Splash *ui; + // Listeners + std::unique_ptr m_handler_init_message; + std::unique_ptr m_handler_show_progress; + std::unique_ptr m_handler_load_wallet; + /** Connect core signals to splash screen */ void subscribeToCoreSignals(); /** Disconnect core signals to splash screen */ diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 8d16eba643e2..cba954370381 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -13,6 +13,7 @@ #include "transactionrecord.h" #include "walletmodel.h" +#include "interfaces/handler.h" #include "sync.h" #include "uint256.h" #include "util.h" @@ -883,13 +884,13 @@ static void ShowProgress(TransactionTableModel* ttm, const std::string& title, i void TransactionTableModel::subscribeToCoreSignals() { // Connect signals to wallet - wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3)); - wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2)); + m_handler_transaction_changed = interfaces::MakeHandler(wallet->NotifyTransactionChanged.connect(std::bind(NotifyTransactionChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3))); + m_handler_show_progress = interfaces::MakeHandler(wallet->ShowProgress.connect(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2))); } void TransactionTableModel::unsubscribeFromCoreSignals() { // Disconnect signals from wallet - wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3)); - wallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); + m_handler_transaction_changed->disconnect(); + m_handler_show_progress->disconnect(); } diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h index 4922bc31057f..b5f925472b2d 100644 --- a/src/qt/transactiontablemodel.h +++ b/src/qt/transactiontablemodel.h @@ -11,6 +11,12 @@ #include #include +#include + +namespace interfaces { + class Handler; +} + class TransactionRecord; class TransactionTablePriv; class WalletModel; @@ -83,6 +89,10 @@ class TransactionTableModel : public QAbstractTableModel void txArrived(const QString& hash, const bool& isCoinStake, const bool& isCSAnyType); private: + // Listeners + std::unique_ptr m_handler_transaction_changed; + std::unique_ptr m_handler_show_progress; + CWallet* wallet; WalletModel* walletModel; QStringList columns; diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 8eb94ec08e3c..d344bb8e4f24 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -16,6 +16,7 @@ #include "coincontrol.h" #include "db.h" #include "keystore.h" +#include "interfaces/handler.h" #include "sapling/key_io_sapling.h" #include "sapling/sapling_operation.h" #include "spork.h" @@ -757,23 +758,23 @@ static void NotifyWalletBacked(WalletModel* model, const bool& fSuccess, const s void WalletModel::subscribeToCoreSignals() { // Connect signals to wallet - wallet->NotifyStatusChanged.connect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1)); - wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6)); - wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3)); - wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2)); - wallet->NotifyWatchonlyChanged.connect(boost::bind(NotifyWatchonlyChanged, this, _1)); - wallet->NotifyWalletBacked.connect(boost::bind(NotifyWalletBacked, this, _1, _2)); + m_handler_notify_status_changed = interfaces::MakeHandler(wallet->NotifyStatusChanged.connect(std::bind(&NotifyKeyStoreStatusChanged, this, std::placeholders::_1))); + m_handler_notify_addressbook_changed = interfaces::MakeHandler(wallet->NotifyAddressBookChanged.connect(std::bind(NotifyAddressBookChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6))); + m_handler_notify_transaction_changed = interfaces::MakeHandler(wallet->NotifyTransactionChanged.connect(std::bind(NotifyTransactionChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3))); + m_handler_show_progress = interfaces::MakeHandler(wallet->ShowProgress.connect(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2))); + m_handler_notify_watch_only_changed = interfaces::MakeHandler(wallet->NotifyWatchonlyChanged.connect(std::bind(NotifyWatchonlyChanged, this, std::placeholders::_1))); + m_handler_notify_walletbacked = interfaces::MakeHandler(wallet->NotifyWalletBacked.connect(std::bind(NotifyWalletBacked, this, std::placeholders::_1, std::placeholders::_2))); } void WalletModel::unsubscribeFromCoreSignals() { // Disconnect signals from wallet - wallet->NotifyStatusChanged.disconnect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1)); - wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6)); - wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3)); - wallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); - wallet->NotifyWatchonlyChanged.disconnect(boost::bind(NotifyWatchonlyChanged, this, _1)); - wallet->NotifyWalletBacked.disconnect(boost::bind(NotifyWalletBacked, this, _1, _2)); + m_handler_notify_status_changed->disconnect(); + m_handler_notify_addressbook_changed->disconnect(); + m_handler_notify_transaction_changed->disconnect(); + m_handler_show_progress->disconnect(); + m_handler_notify_watch_only_changed->disconnect(); + m_handler_notify_walletbacked->disconnect(); } // WalletModel::UnlockContext implementation diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index df21188762cb..02d3a43cfc14 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -11,7 +11,7 @@ #include "paymentrequestplus.h" #include "walletmodeltransaction.h" -#include "interface/wallet.h" +#include "interfaces/wallet.h" #include "allocators.h" /* for SecureString */ #include "operationresult.h" @@ -38,6 +38,10 @@ class CPubKey; class CWallet; class uint256; +namespace interfaces { + class Handler; +}; + QT_BEGIN_NAMESPACE class QTimer; QT_END_NAMESPACE @@ -330,6 +334,14 @@ class WalletModel : public QObject // in the model only perform the data organization (and QT wrappers) to be presented on the UI. interfaces::Wallet walletWrapper; + // Listeners + std::unique_ptr m_handler_notify_status_changed; + std::unique_ptr m_handler_notify_addressbook_changed; + std::unique_ptr m_handler_notify_transaction_changed; + std::unique_ptr m_handler_show_progress; + std::unique_ptr m_handler_notify_watch_only_changed; + std::unique_ptr m_handler_notify_walletbacked; + bool fHaveWatchOnly; bool fForceCheckBalanceChanged; diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 419c04c90c9b..1baaa3db65e9 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -20,7 +20,6 @@ #include "wallet/wallet.h" #endif // ENABLE_WALLET -#include #include #include @@ -58,12 +57,12 @@ void RPCServer::OnStopped(std::function slot) void RPCServer::OnPreCommand(std::function slot) { - g_rpcSignals.PreCommand.connect(boost::bind(slot, _1)); + g_rpcSignals.PreCommand.connect(std::bind(slot, std::placeholders::_1)); } void RPCServer::OnPostCommand(std::function slot) { - g_rpcSignals.PostCommand.connect(boost::bind(slot, _1)); + g_rpcSignals.PostCommand.connect(std::bind(slot, std::placeholders::_1)); } void RPCTypeCheck(const UniValue& params, @@ -454,11 +453,7 @@ UniValue CRPCTable::execute(const JSONRPCRequest &request) const std::vector CRPCTable::listCommands() const { std::vector commandList; - typedef std::map commandMap; - - std::transform( mapCommands.begin(), mapCommands.end(), - std::back_inserter(commandList), - boost::bind(&commandMap::value_type::first,_1) ); + for (const auto& i : mapCommands) commandList.emplace_back(i.first); return commandList; } diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 90110f20750c..e757e9ffa8d9 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -9,7 +9,6 @@ #include "reverselock.h" #include -#include #include CScheduler::CScheduler() : nThreadsServicingQueue(0), stopRequested(false), stopWhenEmpty(false) @@ -102,12 +101,12 @@ void CScheduler::scheduleFromNow(CScheduler::Function f, int64_t deltaSeconds) static void Repeat(CScheduler* s, CScheduler::Function f, int64_t deltaSeconds) { f(); - s->scheduleFromNow(boost::bind(&Repeat, s, f, deltaSeconds), deltaSeconds); + s->scheduleFromNow(std::bind(&Repeat, s, f, deltaSeconds), deltaSeconds); } void CScheduler::scheduleEvery(CScheduler::Function f, int64_t deltaSeconds) { - scheduleFromNow(boost::bind(&Repeat, this, f, deltaSeconds), deltaSeconds); + scheduleFromNow(std::bind(&Repeat, this, f, deltaSeconds), deltaSeconds); } size_t CScheduler::getQueueInfo(boost::chrono::system_clock::time_point &first, diff --git a/src/scheduler.h b/src/scheduler.h index 9c1a62cc9308..ced6098958f4 100644 --- a/src/scheduler.h +++ b/src/scheduler.h @@ -23,8 +23,8 @@ // // CScheduler* s = new CScheduler(); // s->scheduleFromNow(doSomething, 11); // Assuming a: void doSomething() { } -// s->scheduleFromNow(boost::bind(Class::func, this, argument), 3); -// boost::thread* t = new boost::thread(boost::bind(CScheduler::serviceQueue, s)); +// s->scheduleFromNow(std::bind(Class::func, this, argument), 3); +// boost::thread* t = new boost::thread(std::bind(CScheduler::serviceQueue, s)); // // ... then at program shutdown, clean up the thread running serviceQueue: // t->interrupt(); diff --git a/src/test/reverselock_tests.cpp b/src/test/reverselock_tests.cpp index 99c63c55f6d8..6777a5298474 100644 --- a/src/test/reverselock_tests.cpp +++ b/src/test/reverselock_tests.cpp @@ -5,7 +5,6 @@ #include "reverselock.h" -#include #include #include #include diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp index a413877e08aa..ce46cbf5887f 100644 --- a/src/test/scheduler_tests.cpp +++ b/src/test/scheduler_tests.cpp @@ -9,7 +9,6 @@ #include "config/pivx-config.h" #endif -#include #include #include #include @@ -25,7 +24,7 @@ static void microTask(CScheduler& s, boost::mutex& mutex, int& counter, int delt } boost::chrono::system_clock::time_point noTime = boost::chrono::system_clock::time_point::min(); if (rescheduleTime != noTime) { - CScheduler::Function f = boost::bind(µTask, boost::ref(s), boost::ref(mutex), boost::ref(counter), -delta + 1, noTime); + CScheduler::Function f = std::bind(µTask, std::ref(s), std::ref(mutex), std::ref(counter), -delta + 1, noTime); s.schedule(f, rescheduleTime); } } @@ -66,8 +65,8 @@ BOOST_AUTO_TEST_CASE(manythreads) boost::chrono::system_clock::time_point t = now + boost::chrono::microseconds(randomMsec(rng)); boost::chrono::system_clock::time_point tReschedule = now + boost::chrono::microseconds(500 + randomMsec(rng)); int whichCounter = zeroToNine(rng); - CScheduler::Function f = boost::bind(µTask, boost::ref(microTasks), - boost::ref(counterMutex[whichCounter]), boost::ref(counter[whichCounter]), + CScheduler::Function f = std::bind(µTask, std::ref(microTasks), + std::ref(counterMutex[whichCounter]), std::ref(counter[whichCounter]), randomDelta(rng), tReschedule); microTasks.schedule(f, t); } @@ -79,20 +78,20 @@ BOOST_AUTO_TEST_CASE(manythreads) // As soon as these are created they will start running and servicing the queue boost::thread_group microThreads; for (int i = 0; i < 5; i++) - microThreads.create_thread(boost::bind(&CScheduler::serviceQueue, µTasks)); + microThreads.create_thread(std::bind(&CScheduler::serviceQueue, µTasks)); MicroSleep(600); now = boost::chrono::system_clock::now(); // More threads and more tasks: for (int i = 0; i < 5; i++) - microThreads.create_thread(boost::bind(&CScheduler::serviceQueue, µTasks)); + microThreads.create_thread(std::bind(&CScheduler::serviceQueue, µTasks)); for (int i = 0; i < 100; i++) { boost::chrono::system_clock::time_point t = now + boost::chrono::microseconds(randomMsec(rng)); boost::chrono::system_clock::time_point tReschedule = now + boost::chrono::microseconds(500 + randomMsec(rng)); int whichCounter = zeroToNine(rng); - CScheduler::Function f = boost::bind(µTask, boost::ref(microTasks), - boost::ref(counterMutex[whichCounter]), boost::ref(counter[whichCounter]), + CScheduler::Function f = std::bind(µTask, std::ref(microTasks), + std::ref(counterMutex[whichCounter]), std::ref(counter[whichCounter]), randomDelta(rng), tReschedule); microTasks.schedule(f, t); } diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 1da983ae5694..0be88c2f1faf 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -374,7 +374,7 @@ BOOST_AUTO_TEST_CASE(test_big_witness_transaction) { CCheckQueueControl control(&scriptcheckqueue); for (int i=0; i<20; i++) - threadGroup.create_thread(boost::bind(&CCheckQueue::Thread, boost::ref(scriptcheckqueue))); + threadGroup.create_thread(std::bind(&CCheckQueue::Thread, std::ref(scriptcheckqueue))); std::vector coins; for(uint32_t i = 0; i < mtx.vin.size(); i++) { diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 6e698bfd6cd2..e35a43b79658 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -18,7 +18,6 @@ #include #include -#include #include #include #include @@ -463,8 +462,8 @@ TorController::TorController(struct event_base* _base, const std::string& _targe if (!reconnect_ev) LogPrintf("tor: Failed to create event for reconnection: out of memory?\n"); // Start connection attempts immediately - if (!conn.Connect(_target, boost::bind(&TorController::connected_cb, this, _1), - boost::bind(&TorController::disconnected_cb, this, _1) )) { + if (!conn.Connect(_target, std::bind(&TorController::connected_cb, this, std::placeholders::_1), + std::bind(&TorController::disconnected_cb, this, std::placeholders::_1) )) { LogPrintf("tor: Initiating connection to Tor control port %s failed\n", _target); } // Read service private key if cached @@ -541,7 +540,7 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply& // Request hidden service, redirect port. // Note that the 'virtual' port is always the default port to avoid decloaking nodes using other ports. _conn.Command(strprintf("ADD_ONION %s Port=%i,127.0.0.1:%i", private_key, Params().GetDefaultPort(), GetListenPort()), - boost::bind(&TorController::add_onion_cb, this, _1, _2)); + std::bind(&TorController::add_onion_cb, this, std::placeholders::_1, std::placeholders::_2)); } else { LogPrintf("tor: Authentication failed\n"); } @@ -600,7 +599,7 @@ void TorController::authchallenge_cb(TorControlConnection& _conn, const TorContr } std::vector computedClientHash = ComputeResponse(TOR_SAFE_CLIENTKEY, cookie, clientNonce, serverNonce); - _conn.Command("AUTHENTICATE " + HexStr(computedClientHash), boost::bind(&TorController::auth_cb, this, _1, _2)); + _conn.Command("AUTHENTICATE " + HexStr(computedClientHash), std::bind(&TorController::auth_cb, this, std::placeholders::_1, std::placeholders::_2)); } else { LogPrintf("tor: Invalid reply to AUTHCHALLENGE\n"); } @@ -649,23 +648,23 @@ void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorContro if (methods.count("HASHEDPASSWORD")) { LogPrint(BCLog::TOR, "tor: Using HASHEDPASSWORD authentication\n"); boost::replace_all(torpassword, "\"", "\\\""); - _conn.Command("AUTHENTICATE \"" + torpassword + "\"", boost::bind(&TorController::auth_cb, this, _1, _2)); + _conn.Command("AUTHENTICATE \"" + torpassword + "\"", std::bind(&TorController::auth_cb, this, std::placeholders::_1, std::placeholders::_2)); } else { LogPrintf("tor: Password provided with -torpassword, but HASHEDPASSWORD authentication is not available\n"); } } else if (methods.count("NULL")) { LogPrint(BCLog::TOR, "tor: Using NULL authentication\n"); - _conn.Command("AUTHENTICATE", boost::bind(&TorController::auth_cb, this, _1, _2)); + _conn.Command("AUTHENTICATE", std::bind(&TorController::auth_cb, this, std::placeholders::_1, std::placeholders::_2)); } else if (methods.count("SAFECOOKIE")) { // Cookie: hexdump -e '32/1 "%02x""\n"' ~/.tor/control_auth_cookie LogPrint(BCLog::TOR, "tor: Using SAFECOOKIE authentication, reading cookie authentication from %s\n", cookiefile); std::pair status_cookie = ReadBinaryFile(cookiefile, TOR_COOKIE_SIZE); if (status_cookie.first && status_cookie.second.size() == TOR_COOKIE_SIZE) { - // _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), boost::bind(&TorController::auth_cb, this, _1, _2)); + // _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), std::bind(&TorController::auth_cb, this, std::placeholders::_1, std::placeholders::_2)); cookie = std::vector(status_cookie.second.begin(), status_cookie.second.end()); clientNonce = std::vector(TOR_NONCE_SIZE, 0); GetRandBytes(&clientNonce[0], TOR_NONCE_SIZE); - _conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), boost::bind(&TorController::authchallenge_cb, this, _1, _2)); + _conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), std::bind(&TorController::authchallenge_cb, this, std::placeholders::_1, std::placeholders::_2)); } else { if (status_cookie.first) { LogPrintf("tor: Authentication cookie %s is not exactly %i bytes, as is required by the spec\n", cookiefile, TOR_COOKIE_SIZE); @@ -687,7 +686,7 @@ void TorController::connected_cb(TorControlConnection& _conn) { reconnect_timeout = RECONNECT_TIMEOUT_START; // First send a PROTOCOLINFO command to figure out what authentication is expected - if (!_conn.Command("PROTOCOLINFO 1", boost::bind(&TorController::protocolinfo_cb, this, _1, _2))) + if (!_conn.Command("PROTOCOLINFO 1", std::bind(&TorController::protocolinfo_cb, this, std::placeholders::_1, std::placeholders::_2))) LogPrintf("tor: Error sending initial protocolinfo command\n"); } @@ -714,8 +713,8 @@ void TorController::Reconnect() /* Try to reconnect and reestablish if we get booted - for example, Tor * may be restarting. */ - if (!conn.Connect(target, boost::bind(&TorController::connected_cb, this, _1), - boost::bind(&TorController::disconnected_cb, this, _1) )) { + if (!conn.Connect(target, std::bind(&TorController::connected_cb, this, std::placeholders::_1), + std::bind(&TorController::disconnected_cb, this, std::placeholders::_1) )) { LogPrintf("tor: Re-initiating connection to Tor control port %s failed\n", target); } } diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 5cade2edc83f..addcc91f29fa 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -6,8 +6,54 @@ #include "validationinterface.h" +#include +#include + +struct ValidationInterfaceConnections { + boost::signals2::scoped_connection UpdatedBlockTip; + boost::signals2::scoped_connection SyncTransaction; + boost::signals2::scoped_connection NotifyTransactionLock; + boost::signals2::scoped_connection UpdatedTransaction; + boost::signals2::scoped_connection SetBestChain; + boost::signals2::scoped_connection Broadcast; + boost::signals2::scoped_connection BlockChecked; + boost::signals2::scoped_connection BlockFound; + boost::signals2::scoped_connection ChainTip; +}; + +struct MainSignalsInstance { +// XX42 boost::signals2::signal EraseTransaction; + /** Notifies listeners of updated block chain tip */ + boost::signals2::signal UpdatedBlockTip; + /** A posInBlock value for SyncTransaction which indicates the transaction was conflicted, disconnected, or not in a block */ + static const int SYNC_TRANSACTION_NOT_IN_BLOCK = -1; + /** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */ + boost::signals2::signal SyncTransaction; + /** Notifies listeners of an updated transaction lock without new data. */ + boost::signals2::signal NotifyTransactionLock; + /** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */ + boost::signals2::signal UpdatedTransaction; + /** Notifies listeners of a new active block chain. */ + boost::signals2::signal SetBestChain; + /** Tells listeners to broadcast their data. */ + boost::signals2::signal Broadcast; + /** Notifies listeners of a block validation result */ + boost::signals2::signal BlockChecked; + /** Notifies listeners that a block has been successfully mined */ + boost::signals2::signal BlockFound; + + /** Notifies listeners of a change to the tip of the active block chain. */ + boost::signals2::signal)> ChainTip; + + std::unordered_map m_connMainSignals; +}; + static CMainSignals g_signals; +CMainSignals::CMainSignals() { + m_internals.reset(new MainSignalsInstance()); +} + CMainSignals& GetMainSignals() { return g_signals; @@ -15,39 +61,65 @@ CMainSignals& GetMainSignals() void RegisterValidationInterface(CValidationInterface* pwalletIn) { - g_signals.UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); - g_signals.SyncTransaction.connect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2, _3)); - g_signals.ChainTip.connect(boost::bind(&CValidationInterface::ChainTip, pwalletIn, _1, _2, _3)); - g_signals.NotifyTransactionLock.connect(boost::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, _1)); - g_signals.UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); - g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); - g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); - g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); - g_signals.BlockFound.connect(boost::bind(&CValidationInterface::ResetRequestCount, pwalletIn, _1)); + ValidationInterfaceConnections& conns = g_signals.m_internals->m_connMainSignals[pwalletIn]; + conns.UpdatedBlockTip = g_signals.m_internals->UpdatedBlockTip.connect(std::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + conns.SyncTransaction = g_signals.m_internals->SyncTransaction.connect(std::bind(&CValidationInterface::SyncTransaction, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + conns.ChainTip = g_signals.m_internals->ChainTip.connect(std::bind(&CValidationInterface::ChainTip, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + conns.NotifyTransactionLock = g_signals.m_internals->NotifyTransactionLock.connect(std::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, std::placeholders::_1)); + conns.UpdatedTransaction = g_signals.m_internals->UpdatedTransaction.connect(std::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, std::placeholders::_1)); + conns.SetBestChain = g_signals.m_internals->SetBestChain.connect(std::bind(&CValidationInterface::SetBestChain, pwalletIn, std::placeholders::_1)); + conns.Broadcast = g_signals.m_internals->Broadcast.connect(std::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, std::placeholders::_1)); + conns.BlockChecked = g_signals.m_internals->BlockChecked.connect(std::bind(&CValidationInterface::BlockChecked, pwalletIn, std::placeholders::_1, std::placeholders::_2)); + conns.BlockFound = g_signals.m_internals->BlockFound.connect(std::bind(&CValidationInterface::ResetRequestCount, pwalletIn, std::placeholders::_1)); } void UnregisterValidationInterface(CValidationInterface* pwalletIn) { - g_signals.BlockFound.disconnect(boost::bind(&CValidationInterface::ResetRequestCount, pwalletIn, _1)); - g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); - g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); - g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); - g_signals.UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); - g_signals.NotifyTransactionLock.disconnect(boost::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, _1)); - g_signals.SyncTransaction.disconnect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2, _3)); - g_signals.ChainTip.disconnect(boost::bind(&CValidationInterface::ChainTip, pwalletIn, _1, _2, _3)); - g_signals.UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); + if (g_signals.m_internals) { + g_signals.m_internals->m_connMainSignals.erase(pwalletIn); + } } void UnregisterAllValidationInterfaces() { - g_signals.BlockFound.disconnect_all_slots(); - g_signals.BlockChecked.disconnect_all_slots(); - g_signals.Broadcast.disconnect_all_slots(); - g_signals.SetBestChain.disconnect_all_slots(); - g_signals.UpdatedTransaction.disconnect_all_slots(); - g_signals.NotifyTransactionLock.disconnect_all_slots(); - g_signals.SyncTransaction.disconnect_all_slots(); - g_signals.ChainTip.disconnect_all_slots(); - g_signals.UpdatedBlockTip.disconnect_all_slots(); + if (!g_signals.m_internals) { + return; + } + g_signals.m_internals->m_connMainSignals.clear(); +} + +void CMainSignals::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) { + m_internals->UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload); +} + +void CMainSignals::SyncTransaction(const CTransaction& tx, const CBlockIndex* pindex, int posInBlock) { + m_internals->SyncTransaction(tx, pindex, posInBlock); +} + +void CMainSignals::NotifyTransactionLock(const CTransaction& tx) { + m_internals->NotifyTransactionLock(tx); +} + +void CMainSignals::UpdatedTransaction(const uint256& hash) { + m_internals->UpdatedTransaction(hash); +} + +void CMainSignals::SetBestChain(const CBlockLocator& locator) { + m_internals->SetBestChain(locator); +} + +void CMainSignals::Broadcast(CConnman* connman) { + m_internals->Broadcast(connman); +} + +void CMainSignals::BlockChecked(const CBlock& block, const CValidationState& state) { + m_internals->BlockChecked(block, state); } + +void CMainSignals::BlockFound(const uint256& hash) { + m_internals->BlockFound(hash); +} + +void CMainSignals::ChainTip(const CBlockIndex* pindex, const CBlock* block, Optional tree) { + m_internals->ChainTip(pindex, block, tree); +} \ No newline at end of file diff --git a/src/validationinterface.h b/src/validationinterface.h index ad353dfe2996..3519791c7404 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -10,8 +10,6 @@ #include "optional.h" #include "sapling/incrementalmerkletree.h" -#include - class CBlock; struct CBlockLocator; class CBlockIndex; @@ -33,12 +31,15 @@ void UnregisterAllValidationInterfaces(); class CValidationInterface { protected: + /** Notifies listeners of updated block chain tip */ virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {} virtual void SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock) {} virtual void ChainTip(const CBlockIndex *pindex, const CBlock *pblock, Optional added) {} virtual void NotifyTransactionLock(const CTransaction &tx) {} + /** Notifies listeners of the new active block chain on-disk. */ virtual void SetBestChain(const CBlockLocator &locator) {} virtual bool UpdatedTransaction(const uint256 &hash) { return false;} + /** Tells listeners to broadcast their data. */ virtual void ResendWalletTransactions(CConnman* connman) {} virtual void BlockChecked(const CBlock&, const CValidationState&) {} virtual void ResetRequestCount(const uint256 &hash) {}; @@ -47,29 +48,29 @@ class CValidationInterface { friend void ::UnregisterAllValidationInterfaces(); }; -struct CMainSignals { -// XX42 boost::signals2::signal EraseTransaction; - /** Notifies listeners of updated block chain tip */ - boost::signals2::signal UpdatedBlockTip; +struct MainSignalsInstance; +class CMainSignals { +private: + std::unique_ptr m_internals; + + friend void ::RegisterValidationInterface(CValidationInterface*); + friend void ::UnregisterValidationInterface(CValidationInterface*); + friend void ::UnregisterAllValidationInterfaces(); +public: + CMainSignals(); + /** A posInBlock value for SyncTransaction which indicates the transaction was conflicted, disconnected, or not in a block */ static const int SYNC_TRANSACTION_NOT_IN_BLOCK = -1; - /** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */ - boost::signals2::signal SyncTransaction; - /** Notifies listeners of an updated transaction lock without new data. */ - boost::signals2::signal NotifyTransactionLock; - /** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */ - boost::signals2::signal UpdatedTransaction; - /** Notifies listeners of a new active block chain. */ - boost::signals2::signal SetBestChain; - /** Tells listeners to broadcast their data. */ - boost::signals2::signal Broadcast; - /** Notifies listeners of a block validation result */ - boost::signals2::signal BlockChecked; - /** Notifies listeners that a block has been successfully mined */ - boost::signals2::signal BlockFound; - /** Notifies listeners of a change to the tip of the active block chain. */ - boost::signals2::signal)> ChainTip; + void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload); + void SyncTransaction(const CTransaction &, const CBlockIndex *pindex, int posInBlock); + void NotifyTransactionLock(const CTransaction&); + void UpdatedTransaction(const uint256 &); + void SetBestChain(const CBlockLocator &); + void Broadcast(CConnman* connman); + void BlockChecked(const CBlock&, const CValidationState&); + void BlockFound(const uint256&); + void ChainTip(const CBlockIndex *, const CBlock *, Optional); }; CMainSignals& GetMainSignals(); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index f30dde94c4a2..e7583b5f1b6d 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3116,7 +3116,7 @@ UniValue walletpassphrase(const JSONRPCRequest& request) if (nSleepTime > 0) { nWalletUnlockTime = GetTime () + nSleepTime; - RPCRunLater ("lockwallet", boost::bind (LockWallet, pwalletMain), nSleepTime); + RPCRunLater ("lockwallet", std::bind (LockWallet, pwalletMain), nSleepTime); } return NullUniValue; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 16b1d9b4ed85..79b6a4e752cc 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -1043,7 +1043,9 @@ bool AttemptBackupWallet(const CWallet& wallet, const fs::path& pathSrc, const f LogPrintf("cannot backup to wallet source file %s\n", pathDest.string()); return false; } -#if BOOST_VERSION >= 105800 /* BOOST_LIB_VERSION 1_58 */ +#if BOOST_VERSION >= 107400 + fs::copy_file(pathSrc.c_str(), pathDest, fs::copy_options::overwrite_existing); +#elif BOOST_VERSION >= 105800 /* BOOST_LIB_VERSION 1_58 */ fs::copy_file(pathSrc.c_str(), pathDest, fs::copy_option::overwrite_if_exists); #else std::ifstream src(pathSrc.c_str(), std::ios::binary | std::ios::in);