Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down Expand Up @@ -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 \
Expand Down Expand Up @@ -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 \
Expand Down
122 changes: 83 additions & 39 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -1005,7 +1014,7 @@ bool AppInit2()
const std::vector<std::string>& 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));
Expand All @@ -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."));
Expand All @@ -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<int>(std::max<int>(gArgs.GetArg("-checkmempool", Params().DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
int ratio = std::min<int>(
std::max<int>(gArgs.GetArg("-checkmempool", Params().DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
if (ratio != 0) {
mempool.setSanityCheck(1.0 / ratio);
}
Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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);

Expand All @@ -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();
Expand All @@ -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());
Expand All @@ -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;
Expand All @@ -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<CScheduler::Function>, "scheduler", serviceLoop));
CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler);
threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop));

// Initialize Sapling circuit parameters
LoadSaplingParams();
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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
Expand Down
19 changes: 18 additions & 1 deletion src/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
33 changes: 33 additions & 0 deletions src/interfaces/handler.cpp
Original file line number Diff line number Diff line change
@@ -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 <interfaces/handler.h>

#include <util/memory.h>

#include <boost/signals2/connection.hpp>
#include <utility>

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<Handler> MakeHandler(boost::signals2::connection connection)
{
return MakeUnique<HandlerImpl>(std::move(connection));
}

} // namespace interfaces
36 changes: 36 additions & 0 deletions src/interfaces/handler.h
Original file line number Diff line number Diff line change
@@ -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 <memory>

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<Handler> MakeHandler(boost::signals2::connection connection);

} // namespace interfaces

#endif // PIVX_INTERFACES_HANDLER_H
2 changes: 1 addition & 1 deletion src/interface/wallet.cpp → src/interfaces/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
File renamed without changes.
Loading