Changeset View
Changeset View
Standalone View
Standalone View
src/init.cpp
Show First 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | NODISCARD static bool CreatePidFile() { | ||||
if (file) { | if (file) { | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
tfm::format(file, "%d\n", GetCurrentProcessId()); | tfm::format(file, "%d\n", GetCurrentProcessId()); | ||||
#else | #else | ||||
tfm::format(file, "%d\n", getpid()); | tfm::format(file, "%d\n", getpid()); | ||||
#endif | #endif | ||||
return true; | return true; | ||||
} else { | } else { | ||||
return InitError( | return InitError(strprintf(_("Unable to create the PID file '%s': %s"), | ||||
strprintf(_("Unable to create the PID file '%s': %s").translated, | GetPidFile().string(), | ||||
GetPidFile().string(), std::strerror(errno))); | std::strerror(errno))); | ||||
} | } | ||||
} | } | ||||
////////////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////////////// | ||||
// | // | ||||
// Shutdown | // Shutdown | ||||
// | // | ||||
▲ Show 20 Lines • Show All 1,252 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/** Sanity checks | /** Sanity checks | ||||
* Ensure that Bitcoin is running in a usable environment with all | * Ensure that Bitcoin is running in a usable environment with all | ||||
* necessary library support. | * necessary library support. | ||||
*/ | */ | ||||
static bool InitSanityCheck() { | static bool InitSanityCheck() { | ||||
if (!ECC_InitSanityCheck()) { | if (!ECC_InitSanityCheck()) { | ||||
InitError( | return InitError(Untranslated( | ||||
"Elliptic curve cryptography sanity check failure. Aborting."); | "Elliptic curve cryptography sanity check failure. Aborting.")); | ||||
return false; | |||||
} | } | ||||
if (!glibcxx_sanity_test()) { | if (!glibcxx_sanity_test()) { | ||||
return false; | return false; | ||||
} | } | ||||
if (!Random_SanityCheck()) { | if (!Random_SanityCheck()) { | ||||
InitError("OS cryptographic RNG sanity check failure. Aborting."); | return InitError(Untranslated( | ||||
return false; | "OS cryptographic RNG sanity check failure. Aborting.")); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
static bool AppInitServers(Config &config, | static bool AppInitServers(Config &config, | ||||
HTTPRPCRequestProcessor &httpRPCRequestProcessor) { | HTTPRPCRequestProcessor &httpRPCRequestProcessor) { | ||||
RPCServerSignals::OnStarted(&OnRPCStarted); | RPCServerSignals::OnStarted(&OnRPCStarted); | ||||
▲ Show 20 Lines • Show All 186 Lines • ▼ Show 20 Lines | #ifdef _MSC_VER | ||||
_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); | _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); | ||||
#endif | #endif | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
// Enable Data Execution Prevention (DEP) | // Enable Data Execution Prevention (DEP) | ||||
SetProcessDEPPolicy(PROCESS_DEP_ENABLE); | SetProcessDEPPolicy(PROCESS_DEP_ENABLE); | ||||
#endif | #endif | ||||
if (!SetupNetworking()) { | if (!SetupNetworking()) { | ||||
return InitError("Initializing networking failed"); | return InitError(Untranslated("Initializing networking failed")); | ||||
} | } | ||||
#ifndef WIN32 | #ifndef WIN32 | ||||
if (!gArgs.GetBoolArg("-sysperms", false)) { | if (!gArgs.GetBoolArg("-sysperms", false)) { | ||||
umask(077); | umask(077); | ||||
} | } | ||||
// Clean shutdown on SIGTERM | // Clean shutdown on SIGTERM | ||||
Show All 22 Lines | bool AppInitParameterInteraction(Config &config) { | ||||
// also see: InitParameterInteraction() | // also see: InitParameterInteraction() | ||||
// Warn if network-specific options (-addnode, -connect, etc) are | // Warn if network-specific options (-addnode, -connect, etc) are | ||||
// specified in default section of config file, but not overridden | // specified in default section of config file, but not overridden | ||||
// on the command line or in this network's section of the config file. | // on the command line or in this network's section of the config file. | ||||
std::string network = gArgs.GetChainName(); | std::string network = gArgs.GetChainName(); | ||||
for (const auto &arg : gArgs.GetUnsuitableSectionOnlyArgs()) { | for (const auto &arg : gArgs.GetUnsuitableSectionOnlyArgs()) { | ||||
return InitError(strprintf(_("Config setting for %s only applied on %s " | return InitError(strprintf(_("Config setting for %s only applied on %s " | ||||
"network when in [%s] section.") | "network when in [%s] section."), | ||||
.translated, | |||||
arg, network, network)); | arg, network, network)); | ||||
} | } | ||||
// Warn if unrecognized section name are present in the config file. | // Warn if unrecognized section name are present in the config file. | ||||
for (const auto §ion : gArgs.GetUnrecognizedSections()) { | for (const auto §ion : gArgs.GetUnrecognizedSections()) { | ||||
InitWarning(strprintf( | InitWarning(strprintf( | ||||
"%s:%i " + _("Section [%s] is not recognized.").translated, | "%s:%i " + _("Section [%s] is not recognized.").translated, | ||||
section.m_file, section.m_line, section.m_name)); | section.m_file, section.m_line, section.m_name)); | ||||
} | } | ||||
if (!fs::is_directory(GetBlocksDir())) { | if (!fs::is_directory(GetBlocksDir())) { | ||||
return InitError(strprintf( | return InitError( | ||||
_("Specified blocks directory \"%s\" does not exist.").translated, | strprintf(_("Specified blocks directory \"%s\" does not exist."), | ||||
gArgs.GetArg("-blocksdir", ""))); | gArgs.GetArg("-blocksdir", ""))); | ||||
} | } | ||||
// parse and validate enabled filter types | // parse and validate enabled filter types | ||||
std::string blockfilterindex_value = | std::string blockfilterindex_value = | ||||
gArgs.GetArg("-blockfilterindex", DEFAULT_BLOCKFILTERINDEX); | gArgs.GetArg("-blockfilterindex", DEFAULT_BLOCKFILTERINDEX); | ||||
if (blockfilterindex_value == "" || blockfilterindex_value == "1") { | if (blockfilterindex_value == "" || blockfilterindex_value == "1") { | ||||
g_enabled_filter_types = AllBlockFilterTypes(); | g_enabled_filter_types = AllBlockFilterTypes(); | ||||
} else if (blockfilterindex_value != "0") { | } else if (blockfilterindex_value != "0") { | ||||
const std::vector<std::string> names = | const std::vector<std::string> names = | ||||
gArgs.GetArgs("-blockfilterindex"); | gArgs.GetArgs("-blockfilterindex"); | ||||
g_enabled_filter_types.reserve(names.size()); | g_enabled_filter_types.reserve(names.size()); | ||||
for (const auto &name : names) { | for (const auto &name : names) { | ||||
BlockFilterType filter_type; | BlockFilterType filter_type; | ||||
if (!BlockFilterTypeByName(name, filter_type)) { | if (!BlockFilterTypeByName(name, filter_type)) { | ||||
return InitError(strprintf( | return InitError( | ||||
_("Unknown -blockfilterindex value %s.").translated, name)); | strprintf(_("Unknown -blockfilterindex value %s."), name)); | ||||
} | } | ||||
g_enabled_filter_types.push_back(filter_type); | g_enabled_filter_types.push_back(filter_type); | ||||
} | } | ||||
} | } | ||||
// if using block pruning, then disallow txindex | // if using block pruning, then disallow txindex | ||||
if (gArgs.GetArg("-prune", 0)) { | if (gArgs.GetArg("-prune", 0)) { | ||||
if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) { | if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) { | ||||
return InitError( | return InitError(_("Prune mode is incompatible with -txindex.")); | ||||
_("Prune mode is incompatible with -txindex.").translated); | |||||
} | } | ||||
if (!g_enabled_filter_types.empty()) { | if (!g_enabled_filter_types.empty()) { | ||||
return InitError( | return InitError( | ||||
_("Prune mode is incompatible with -blockfilterindex.") | _("Prune mode is incompatible with -blockfilterindex.")); | ||||
.translated); | |||||
} | } | ||||
} | } | ||||
// -bind and -whitebind can't be set when not listening | // -bind and -whitebind can't be set when not listening | ||||
size_t nUserBind = | size_t nUserBind = | ||||
gArgs.GetArgs("-bind").size() + gArgs.GetArgs("-whitebind").size(); | gArgs.GetArgs("-bind").size() + gArgs.GetArgs("-whitebind").size(); | ||||
if (nUserBind != 0 && !gArgs.GetBoolArg("-listen", DEFAULT_LISTEN)) { | if (nUserBind != 0 && !gArgs.GetBoolArg("-listen", DEFAULT_LISTEN)) { | ||||
return InitError( | return InitError(Untranslated( | ||||
"Cannot set -bind or -whitebind together with -listen=0"); | "Cannot set -bind or -whitebind together with -listen=0")); | ||||
} | } | ||||
// Make sure enough file descriptors are available | // Make sure enough file descriptors are available | ||||
int nBind = std::max(nUserBind, size_t(1)); | int nBind = std::max(nUserBind, size_t(1)); | ||||
nUserMaxConnections = | nUserMaxConnections = | ||||
gArgs.GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS); | gArgs.GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS); | ||||
nMaxConnections = std::max(nUserMaxConnections, 0); | nMaxConnections = std::max(nUserMaxConnections, 0); | ||||
// Trim requested connection counts, to fit into system limitations | // Trim requested connection counts, to fit into system limitations | ||||
// <int> in std::min<int>(...) to work around FreeBSD compilation issue | // <int> in std::min<int>(...) to work around FreeBSD compilation issue | ||||
// described in #2695 | // described in #2695 | ||||
nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS + | nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS + | ||||
MAX_ADDNODE_CONNECTIONS); | MAX_ADDNODE_CONNECTIONS); | ||||
#ifdef USE_POLL | #ifdef USE_POLL | ||||
int fd_max = nFD; | int fd_max = nFD; | ||||
#else | #else | ||||
int fd_max = FD_SETSIZE; | int fd_max = FD_SETSIZE; | ||||
#endif | #endif | ||||
nMaxConnections = | nMaxConnections = | ||||
std::max(std::min<int>(nMaxConnections, fd_max - nBind - | std::max(std::min<int>(nMaxConnections, fd_max - nBind - | ||||
MIN_CORE_FILEDESCRIPTORS - | MIN_CORE_FILEDESCRIPTORS - | ||||
MAX_ADDNODE_CONNECTIONS), | MAX_ADDNODE_CONNECTIONS), | ||||
0); | 0); | ||||
if (nFD < MIN_CORE_FILEDESCRIPTORS) { | if (nFD < MIN_CORE_FILEDESCRIPTORS) { | ||||
return InitError( | return InitError(_("Not enough file descriptors available.")); | ||||
_("Not enough file descriptors available.").translated); | |||||
} | } | ||||
nMaxConnections = | nMaxConnections = | ||||
std::min(nFD - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS, | std::min(nFD - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS, | ||||
nMaxConnections); | nMaxConnections); | ||||
if (nMaxConnections < nUserMaxConnections) { | if (nMaxConnections < nUserMaxConnections) { | ||||
InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, " | InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, " | ||||
"because of system limitations.") | "because of system limitations.") | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | if (!hashAssumeValid.IsNull()) { | ||||
LogPrintf("Validating signatures for all blocks.\n"); | LogPrintf("Validating signatures for all blocks.\n"); | ||||
} | } | ||||
if (gArgs.IsArgSet("-minimumchainwork")) { | if (gArgs.IsArgSet("-minimumchainwork")) { | ||||
const std::string minChainWorkStr = | const std::string minChainWorkStr = | ||||
gArgs.GetArg("-minimumchainwork", ""); | gArgs.GetArg("-minimumchainwork", ""); | ||||
if (!IsHexNumber(minChainWorkStr)) { | if (!IsHexNumber(minChainWorkStr)) { | ||||
return InitError(strprintf( | return InitError(strprintf( | ||||
"Invalid non-hex (%s) minimum chain work value specified", | Untranslated( | ||||
"Invalid non-hex (%s) minimum chain work value specified"), | |||||
minChainWorkStr)); | minChainWorkStr)); | ||||
} | } | ||||
nMinimumChainWork = UintToArith256(uint256S(minChainWorkStr)); | nMinimumChainWork = UintToArith256(uint256S(minChainWorkStr)); | ||||
} else { | } else { | ||||
nMinimumChainWork = | nMinimumChainWork = | ||||
UintToArith256(chainparams.GetConsensus().nMinimumChainWork); | UintToArith256(chainparams.GetConsensus().nMinimumChainWork); | ||||
} | } | ||||
LogPrintf("Setting nMinimumChainWork=%s\n", nMinimumChainWork.GetHex()); | LogPrintf("Setting nMinimumChainWork=%s\n", nMinimumChainWork.GetHex()); | ||||
if (nMinimumChainWork < | if (nMinimumChainWork < | ||||
UintToArith256(chainparams.GetConsensus().nMinimumChainWork)) { | UintToArith256(chainparams.GetConsensus().nMinimumChainWork)) { | ||||
LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", | LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", | ||||
chainparams.GetConsensus().nMinimumChainWork.GetHex()); | chainparams.GetConsensus().nMinimumChainWork.GetHex()); | ||||
} | } | ||||
// mempool limits | // mempool limits | ||||
int64_t nMempoolSizeMax = | int64_t nMempoolSizeMax = | ||||
gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; | gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; | ||||
int64_t nMempoolSizeMin = | int64_t nMempoolSizeMin = | ||||
gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * | gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * | ||||
1000 * 40; | 1000 * 40; | ||||
if (nMempoolSizeMax < 0 || nMempoolSizeMax < nMempoolSizeMin) { | if (nMempoolSizeMax < 0 || nMempoolSizeMax < nMempoolSizeMin) { | ||||
return InitError( | return InitError(strprintf(_("-maxmempool must be at least %d MB"), | ||||
strprintf(_("-maxmempool must be at least %d MB").translated, | |||||
std::ceil(nMempoolSizeMin / 1000000.0))); | std::ceil(nMempoolSizeMin / 1000000.0))); | ||||
} | } | ||||
// Configure excessive block size. | // Configure excessive block size. | ||||
const uint64_t nProposedExcessiveBlockSize = | const uint64_t nProposedExcessiveBlockSize = | ||||
gArgs.GetArg("-excessiveblocksize", DEFAULT_MAX_BLOCK_SIZE); | gArgs.GetArg("-excessiveblocksize", DEFAULT_MAX_BLOCK_SIZE); | ||||
if (!config.SetMaxBlockSize(nProposedExcessiveBlockSize)) { | if (!config.SetMaxBlockSize(nProposedExcessiveBlockSize)) { | ||||
return InitError( | return InitError( | ||||
_("Excessive block size must be > 1,000,000 bytes (1MB)") | _("Excessive block size must be > 1,000,000 bytes (1MB)")); | ||||
.translated); | |||||
} | } | ||||
// Check blockmaxsize does not exceed maximum accepted block size. | // Check blockmaxsize does not exceed maximum accepted block size. | ||||
const uint64_t nProposedMaxGeneratedBlockSize = | const uint64_t nProposedMaxGeneratedBlockSize = | ||||
gArgs.GetArg("-blockmaxsize", DEFAULT_MAX_GENERATED_BLOCK_SIZE); | gArgs.GetArg("-blockmaxsize", DEFAULT_MAX_GENERATED_BLOCK_SIZE); | ||||
if (nProposedMaxGeneratedBlockSize > config.GetMaxBlockSize()) { | if (nProposedMaxGeneratedBlockSize > config.GetMaxBlockSize()) { | ||||
auto msg = _("Max generated block size (blockmaxsize) cannot exceed " | auto msg = _("Max generated block size (blockmaxsize) cannot exceed " | ||||
"the excessive block size (excessiveblocksize)") | "the excessive block size (excessiveblocksize)"); | ||||
.translated; | |||||
return InitError(msg); | return InitError(msg); | ||||
} | } | ||||
// block pruning; get the amount of disk space (in MiB) to allot for block & | // block pruning; get the amount of disk space (in MiB) to allot for block & | ||||
// undo files | // undo files | ||||
int64_t nPruneArg = gArgs.GetArg("-prune", 0); | int64_t nPruneArg = gArgs.GetArg("-prune", 0); | ||||
if (nPruneArg < 0) { | if (nPruneArg < 0) { | ||||
return InitError( | return InitError( | ||||
_("Prune cannot be configured with a negative value.").translated); | _("Prune cannot be configured with a negative value.")); | ||||
} | } | ||||
nPruneTarget = (uint64_t)nPruneArg * 1024 * 1024; | nPruneTarget = (uint64_t)nPruneArg * 1024 * 1024; | ||||
if (nPruneArg == 1) { | if (nPruneArg == 1) { | ||||
// manual pruning: -prune=1 | // manual pruning: -prune=1 | ||||
LogPrintf("Block pruning enabled. Use RPC call " | LogPrintf("Block pruning enabled. Use RPC call " | ||||
"pruneblockchain(height) to manually prune block and undo " | "pruneblockchain(height) to manually prune block and undo " | ||||
"files.\n"); | "files.\n"); | ||||
nPruneTarget = std::numeric_limits<uint64_t>::max(); | nPruneTarget = std::numeric_limits<uint64_t>::max(); | ||||
fPruneMode = true; | fPruneMode = true; | ||||
} else if (nPruneTarget) { | } else if (nPruneTarget) { | ||||
if (nPruneTarget < MIN_DISK_SPACE_FOR_BLOCK_FILES) { | if (nPruneTarget < MIN_DISK_SPACE_FOR_BLOCK_FILES) { | ||||
return InitError( | return InitError( | ||||
strprintf(_("Prune configured below the minimum of %d MiB. " | strprintf(_("Prune configured below the minimum of %d MiB. " | ||||
"Please use a higher number.") | "Please use a higher number."), | ||||
.translated, | |||||
MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024)); | MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024)); | ||||
} | } | ||||
LogPrintf("Prune configured to target %u MiB on disk for block and " | LogPrintf("Prune configured to target %u MiB on disk for block and " | ||||
"undo files.\n", | "undo files.\n", | ||||
nPruneTarget / 1024 / 1024); | nPruneTarget / 1024 / 1024); | ||||
fPruneMode = true; | fPruneMode = true; | ||||
} | } | ||||
nConnectTimeout = gArgs.GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT); | nConnectTimeout = gArgs.GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT); | ||||
if (nConnectTimeout <= 0) { | if (nConnectTimeout <= 0) { | ||||
nConnectTimeout = DEFAULT_CONNECT_TIMEOUT; | nConnectTimeout = DEFAULT_CONNECT_TIMEOUT; | ||||
} | } | ||||
peer_connect_timeout = | peer_connect_timeout = | ||||
gArgs.GetArg("-peertimeout", DEFAULT_PEER_CONNECT_TIMEOUT); | gArgs.GetArg("-peertimeout", DEFAULT_PEER_CONNECT_TIMEOUT); | ||||
if (peer_connect_timeout <= 0) { | if (peer_connect_timeout <= 0) { | ||||
return InitError( | return InitError(Untranslated( | ||||
"peertimeout cannot be configured with a negative value."); | "peertimeout cannot be configured with a negative value.")); | ||||
} | } | ||||
// Obtain the amount to charge excess UTXO | // Obtain the amount to charge excess UTXO | ||||
if (gArgs.IsArgSet("-excessutxocharge")) { | if (gArgs.IsArgSet("-excessutxocharge")) { | ||||
Amount n = Amount::zero(); | Amount n = Amount::zero(); | ||||
auto parsed = ParseMoney(gArgs.GetArg("-excessutxocharge", ""), n); | auto parsed = ParseMoney(gArgs.GetArg("-excessutxocharge", ""), n); | ||||
if (!parsed || Amount::zero() > n) { | if (!parsed || Amount::zero() > n) { | ||||
return InitError(AmountErrMsg("excessutxocharge", | return InitError(AmountErrMsg( | ||||
gArgs.GetArg("-excessutxocharge", "")) | "excessutxocharge", gArgs.GetArg("-excessutxocharge", ""))); | ||||
.translated); | |||||
} | } | ||||
config.SetExcessUTXOCharge(n); | config.SetExcessUTXOCharge(n); | ||||
} else { | } else { | ||||
config.SetExcessUTXOCharge(DEFAULT_UTXO_FEE); | config.SetExcessUTXOCharge(DEFAULT_UTXO_FEE); | ||||
} | } | ||||
if (gArgs.IsArgSet("-minrelaytxfee")) { | if (gArgs.IsArgSet("-minrelaytxfee")) { | ||||
Amount n = Amount::zero(); | Amount n = Amount::zero(); | ||||
auto parsed = ParseMoney(gArgs.GetArg("-minrelaytxfee", ""), n); | auto parsed = ParseMoney(gArgs.GetArg("-minrelaytxfee", ""), n); | ||||
if (!parsed || n == Amount::zero()) { | if (!parsed || n == Amount::zero()) { | ||||
return InitError(AmountErrMsg("minrelaytxfee", | return InitError(AmountErrMsg("minrelaytxfee", | ||||
gArgs.GetArg("-minrelaytxfee", "")) | gArgs.GetArg("-minrelaytxfee", ""))); | ||||
.translated); | |||||
} | } | ||||
// High fee check is done afterward in CWallet::CreateWalletFromFile() | // High fee check is done afterward in CWallet::CreateWalletFromFile() | ||||
::minRelayTxFee = CFeeRate(n); | ::minRelayTxFee = CFeeRate(n); | ||||
} | } | ||||
// Sanity check argument for min fee for including tx in block | // Sanity check argument for min fee for including tx in block | ||||
// TODO: Harmonize which arguments need sanity checking and where that | // TODO: Harmonize which arguments need sanity checking and where that | ||||
// happens. | // happens. | ||||
if (gArgs.IsArgSet("-blockmintxfee")) { | if (gArgs.IsArgSet("-blockmintxfee")) { | ||||
Amount n = Amount::zero(); | Amount n = Amount::zero(); | ||||
if (!ParseMoney(gArgs.GetArg("-blockmintxfee", ""), n)) { | if (!ParseMoney(gArgs.GetArg("-blockmintxfee", ""), n)) { | ||||
return InitError(AmountErrMsg("blockmintxfee", | return InitError(AmountErrMsg("blockmintxfee", | ||||
gArgs.GetArg("-blockmintxfee", "")) | gArgs.GetArg("-blockmintxfee", ""))); | ||||
.translated); | |||||
} | } | ||||
} | } | ||||
// Feerate used to define dust. Shouldn't be changed lightly as old | // Feerate used to define dust. Shouldn't be changed lightly as old | ||||
// implementations may inadvertently create non-standard transactions. | // implementations may inadvertently create non-standard transactions. | ||||
if (gArgs.IsArgSet("-dustrelayfee")) { | if (gArgs.IsArgSet("-dustrelayfee")) { | ||||
Amount n = Amount::zero(); | Amount n = Amount::zero(); | ||||
auto parsed = ParseMoney(gArgs.GetArg("-dustrelayfee", ""), n); | auto parsed = ParseMoney(gArgs.GetArg("-dustrelayfee", ""), n); | ||||
if (!parsed || Amount::zero() == n) { | if (!parsed || Amount::zero() == n) { | ||||
return InitError( | return InitError(AmountErrMsg("dustrelayfee", | ||||
AmountErrMsg("dustrelayfee", gArgs.GetArg("-dustrelayfee", "")) | gArgs.GetArg("-dustrelayfee", ""))); | ||||
.translated); | |||||
} | } | ||||
dustRelayFee = CFeeRate(n); | dustRelayFee = CFeeRate(n); | ||||
} | } | ||||
fRequireStandard = | fRequireStandard = | ||||
!gArgs.GetBoolArg("-acceptnonstdtxn", !chainparams.RequireStandard()); | !gArgs.GetBoolArg("-acceptnonstdtxn", !chainparams.RequireStandard()); | ||||
if (!chainparams.IsTestChain() && !fRequireStandard) { | if (!chainparams.IsTestChain() && !fRequireStandard) { | ||||
return InitError( | return InitError(strprintf( | ||||
strprintf("acceptnonstdtxn is not currently supported for %s chain", | Untranslated( | ||||
"acceptnonstdtxn is not currently supported for %s chain"), | |||||
chainparams.NetworkIDString())); | chainparams.NetworkIDString())); | ||||
} | } | ||||
nBytesPerSigOp = gArgs.GetArg("-bytespersigop", nBytesPerSigOp); | nBytesPerSigOp = gArgs.GetArg("-bytespersigop", nBytesPerSigOp); | ||||
if (!g_wallet_init_interface.ParameterInteraction()) { | if (!g_wallet_init_interface.ParameterInteraction()) { | ||||
return false; | return false; | ||||
} | } | ||||
fIsBareMultisigStd = | fIsBareMultisigStd = | ||||
Show All 18 Lines | #endif | ||||
return true; | return true; | ||||
} | } | ||||
static bool LockDataDirectory(bool probeOnly) { | static bool LockDataDirectory(bool probeOnly) { | ||||
// Make sure only a single Bitcoin process is using the data directory. | // Make sure only a single Bitcoin process is using the data directory. | ||||
fs::path datadir = GetDataDir(); | fs::path datadir = GetDataDir(); | ||||
if (!DirIsWritable(datadir)) { | if (!DirIsWritable(datadir)) { | ||||
return InitError(strprintf( | return InitError(strprintf( | ||||
_("Cannot write to data directory '%s'; check permissions.") | _("Cannot write to data directory '%s'; check permissions."), | ||||
.translated, | |||||
datadir.string())); | datadir.string())); | ||||
} | } | ||||
if (!LockDirectory(datadir, ".lock", probeOnly)) { | if (!LockDirectory(datadir, ".lock", probeOnly)) { | ||||
return InitError(strprintf(_("Cannot obtain a lock on data directory " | return InitError(strprintf(_("Cannot obtain a lock on data directory " | ||||
"%s. %s is probably already running.") | "%s. %s is probably already running."), | ||||
.translated, | |||||
datadir.string(), PACKAGE_NAME)); | datadir.string(), PACKAGE_NAME)); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool AppInitSanityChecks() { | bool AppInitSanityChecks() { | ||||
// Step 4: sanity checks | // Step 4: sanity checks | ||||
// Initialize elliptic curve code | // Initialize elliptic curve code | ||||
std::string sha256_algo = SHA256AutoDetect(); | std::string sha256_algo = SHA256AutoDetect(); | ||||
LogPrintf("Using the '%s' SHA256 implementation\n", sha256_algo); | LogPrintf("Using the '%s' SHA256 implementation\n", sha256_algo); | ||||
RandomInit(); | RandomInit(); | ||||
ECC_Start(); | ECC_Start(); | ||||
globalVerifyHandle.reset(new ECCVerifyHandle()); | globalVerifyHandle.reset(new ECCVerifyHandle()); | ||||
// Sanity check | // Sanity check | ||||
if (!InitSanityCheck()) { | if (!InitSanityCheck()) { | ||||
return InitError(strprintf( | return InitError(strprintf( | ||||
_("Initialization sanity check failed. %s is shutting down.") | _("Initialization sanity check failed. %s is shutting down."), | ||||
.translated, | |||||
PACKAGE_NAME)); | PACKAGE_NAME)); | ||||
} | } | ||||
// Probe the data directory lock to give an early error message, if possible | // Probe the data directory lock to give an early error message, if possible | ||||
// We cannot hold the data directory lock here, as the forking for daemon() | // We cannot hold the data directory lock here, as the forking for daemon() | ||||
// hasn't yet happened, and a fork will cause weird behavior to it. | // hasn't yet happened, and a fork will cause weird behavior to it. | ||||
return LockDataDirectory(true); | return LockDataDirectory(true); | ||||
} | } | ||||
Show All 28 Lines | if (logger.m_print_to_file) { | ||||
// Do this first since it both loads a bunch of debug.log into | // Do this first since it both loads a bunch of debug.log into | ||||
// memory, and because this needs to happen before any other | // memory, and because this needs to happen before any other | ||||
// debug.log printing. | // debug.log printing. | ||||
logger.ShrinkDebugFile(); | logger.ShrinkDebugFile(); | ||||
} | } | ||||
} | } | ||||
if (!logger.StartLogging()) { | if (!logger.StartLogging()) { | ||||
return InitError(strprintf("Could not open debug log file %s", | return InitError( | ||||
strprintf(Untranslated("Could not open debug log file %s"), | |||||
logger.m_file_path.string())); | logger.m_file_path.string())); | ||||
} | } | ||||
if (!logger.m_log_timestamps) { | if (!logger.m_log_timestamps) { | ||||
LogPrintf("Startup time: %s\n", FormatISO8601DateTime(GetTime())); | LogPrintf("Startup time: %s\n", FormatISO8601DateTime(GetTime())); | ||||
} | } | ||||
LogPrintf("Default data directory %s\n", GetDefaultDataDir().string()); | LogPrintf("Default data directory %s\n", GetDefaultDataDir().string()); | ||||
LogPrintf("Using data directory %s\n", GetDataDir().string()); | LogPrintf("Using data directory %s\n", GetDataDir().string()); | ||||
▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | #endif | ||||
* process calls yet (but it will verify that the server is there and will | * process calls yet (but it will verify that the server is there and will | ||||
* be ready later). Warmup mode will be completed when initialisation is | * be ready later). Warmup mode will be completed when initialisation is | ||||
* finished. | * finished. | ||||
*/ | */ | ||||
if (gArgs.GetBoolArg("-server", false)) { | if (gArgs.GetBoolArg("-server", false)) { | ||||
uiInterface.InitMessage_connect(SetRPCWarmupStatus); | uiInterface.InitMessage_connect(SetRPCWarmupStatus); | ||||
if (!AppInitServers(config, httpRPCRequestProcessor)) { | if (!AppInitServers(config, httpRPCRequestProcessor)) { | ||||
return InitError( | return InitError( | ||||
_("Unable to start HTTP server. See debug log for details.") | _("Unable to start HTTP server. See debug log for details.")); | ||||
.translated); | |||||
} | } | ||||
} | } | ||||
// Step 5: verify wallet database integrity | // Step 5: verify wallet database integrity | ||||
for (const auto &client : node.chain_clients) { | for (const auto &client : node.chain_clients) { | ||||
if (!client->verify(chainparams)) { | if (!client->verify(chainparams)) { | ||||
return false; | return false; | ||||
} | } | ||||
Show All 19 Lines | node.peer_logic.reset(new PeerLogicValidation( | ||||
node.connman.get(), node.banman.get(), *node.scheduler)); | node.connman.get(), node.banman.get(), *node.scheduler)); | ||||
RegisterValidationInterface(node.peer_logic.get()); | RegisterValidationInterface(node.peer_logic.get()); | ||||
// sanitize comments per BIP-0014, format user agent and check total size | // sanitize comments per BIP-0014, format user agent and check total size | ||||
std::vector<std::string> uacomments; | std::vector<std::string> uacomments; | ||||
for (const std::string &cmt : gArgs.GetArgs("-uacomment")) { | for (const std::string &cmt : gArgs.GetArgs("-uacomment")) { | ||||
if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT)) { | if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT)) { | ||||
return InitError(strprintf( | return InitError(strprintf( | ||||
_("User Agent comment (%s) contains unsafe characters.") | _("User Agent comment (%s) contains unsafe characters."), cmt)); | ||||
.translated, | |||||
cmt)); | |||||
} | } | ||||
uacomments.push_back(cmt); | uacomments.push_back(cmt); | ||||
} | } | ||||
const std::string strSubVersion = | const std::string strSubVersion = | ||||
FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, uacomments); | FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, uacomments); | ||||
if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) { | if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) { | ||||
return InitError(strprintf( | return InitError(strprintf( | ||||
_("Total length of network version string (%i) exceeds maximum " | _("Total length of network version string (%i) exceeds maximum " | ||||
"length (%i). Reduce the number or size of uacomments.") | "length (%i). Reduce the number or size of uacomments."), | ||||
.translated, | |||||
strSubVersion.size(), MAX_SUBVERSION_LENGTH)); | strSubVersion.size(), MAX_SUBVERSION_LENGTH)); | ||||
} | } | ||||
if (gArgs.IsArgSet("-onlynet")) { | if (gArgs.IsArgSet("-onlynet")) { | ||||
std::set<enum Network> nets; | std::set<enum Network> nets; | ||||
for (const std::string &snet : gArgs.GetArgs("-onlynet")) { | for (const std::string &snet : gArgs.GetArgs("-onlynet")) { | ||||
enum Network net = ParseNetwork(snet); | enum Network net = ParseNetwork(snet); | ||||
if (net == NET_UNROUTABLE) { | if (net == NET_UNROUTABLE) { | ||||
return InitError(strprintf( | return InitError(strprintf( | ||||
_("Unknown network specified in -onlynet: '%s'").translated, | _("Unknown network specified in -onlynet: '%s'"), snet)); | ||||
snet)); | |||||
} | } | ||||
nets.insert(net); | nets.insert(net); | ||||
} | } | ||||
for (int n = 0; n < NET_MAX; n++) { | for (int n = 0; n < NET_MAX; n++) { | ||||
enum Network net = (enum Network)n; | enum Network net = (enum Network)n; | ||||
if (!nets.count(net)) { | if (!nets.count(net)) { | ||||
SetReachable(net, false); | SetReachable(net, false); | ||||
} | } | ||||
Show All 10 Lines | #endif | ||||
// -noproxy (or -proxy=0) as well as the empty string can be used to not set | // -noproxy (or -proxy=0) as well as the empty string can be used to not set | ||||
// a proxy, this is the default | // a proxy, this is the default | ||||
std::string proxyArg = gArgs.GetArg("-proxy", ""); | std::string proxyArg = gArgs.GetArg("-proxy", ""); | ||||
SetReachable(NET_ONION, false); | SetReachable(NET_ONION, false); | ||||
if (proxyArg != "" && proxyArg != "0") { | if (proxyArg != "" && proxyArg != "0") { | ||||
CService proxyAddr; | CService proxyAddr; | ||||
if (!Lookup(proxyArg.c_str(), proxyAddr, 9050, fNameLookup)) { | if (!Lookup(proxyArg.c_str(), proxyAddr, 9050, fNameLookup)) { | ||||
return InitError(strprintf( | return InitError(strprintf( | ||||
_("Invalid -proxy address or hostname: '%s'").translated, | _("Invalid -proxy address or hostname: '%s'"), proxyArg)); | ||||
proxyArg)); | |||||
} | } | ||||
proxyType addrProxy = proxyType(proxyAddr, proxyRandomize); | proxyType addrProxy = proxyType(proxyAddr, proxyRandomize); | ||||
if (!addrProxy.IsValid()) { | if (!addrProxy.IsValid()) { | ||||
return InitError(strprintf( | return InitError(strprintf( | ||||
_("Invalid -proxy address or hostname: '%s'").translated, | _("Invalid -proxy address or hostname: '%s'"), proxyArg)); | ||||
proxyArg)); | |||||
} | } | ||||
SetProxy(NET_IPV4, addrProxy); | SetProxy(NET_IPV4, addrProxy); | ||||
SetProxy(NET_IPV6, addrProxy); | SetProxy(NET_IPV6, addrProxy); | ||||
SetProxy(NET_ONION, addrProxy); | SetProxy(NET_ONION, addrProxy); | ||||
SetNameProxy(addrProxy); | SetNameProxy(addrProxy); | ||||
// by default, -proxy sets onion as reachable, unless -noonion later | // by default, -proxy sets onion as reachable, unless -noonion later | ||||
SetReachable(NET_ONION, true); | SetReachable(NET_ONION, true); | ||||
} | } | ||||
// -onion can be used to set only a proxy for .onion, or override normal | // -onion can be used to set only a proxy for .onion, or override normal | ||||
// proxy for .onion addresses. | // proxy for .onion addresses. | ||||
// -noonion (or -onion=0) disables connecting to .onion entirely. An empty | // -noonion (or -onion=0) disables connecting to .onion entirely. An empty | ||||
// string is used to not override the onion proxy (in which case it defaults | // string is used to not override the onion proxy (in which case it defaults | ||||
// to -proxy set above, or none) | // to -proxy set above, or none) | ||||
std::string onionArg = gArgs.GetArg("-onion", ""); | std::string onionArg = gArgs.GetArg("-onion", ""); | ||||
if (onionArg != "") { | if (onionArg != "") { | ||||
if (onionArg == "0") { | if (onionArg == "0") { | ||||
// Handle -noonion/-onion=0 | // Handle -noonion/-onion=0 | ||||
SetReachable(NET_ONION, false); | SetReachable(NET_ONION, false); | ||||
} else { | } else { | ||||
CService onionProxy; | CService onionProxy; | ||||
if (!Lookup(onionArg.c_str(), onionProxy, 9050, fNameLookup)) { | if (!Lookup(onionArg.c_str(), onionProxy, 9050, fNameLookup)) { | ||||
return InitError(strprintf( | return InitError(strprintf( | ||||
_("Invalid -onion address or hostname: '%s'").translated, | _("Invalid -onion address or hostname: '%s'"), onionArg)); | ||||
onionArg)); | |||||
} | } | ||||
proxyType addrOnion = proxyType(onionProxy, proxyRandomize); | proxyType addrOnion = proxyType(onionProxy, proxyRandomize); | ||||
if (!addrOnion.IsValid()) { | if (!addrOnion.IsValid()) { | ||||
return InitError(strprintf( | return InitError(strprintf( | ||||
_("Invalid -onion address or hostname: '%s'").translated, | _("Invalid -onion address or hostname: '%s'"), onionArg)); | ||||
onionArg)); | |||||
} | } | ||||
SetProxy(NET_ONION, addrOnion); | SetProxy(NET_ONION, addrOnion); | ||||
SetReachable(NET_ONION, true); | SetReachable(NET_ONION, true); | ||||
} | } | ||||
} | } | ||||
// see Step 2: parameter interactions for more information about these | // see Step 2: parameter interactions for more information about these | ||||
fListen = gArgs.GetBoolArg("-listen", DEFAULT_LISTEN); | fListen = gArgs.GetBoolArg("-listen", DEFAULT_LISTEN); | ||||
fDiscover = gArgs.GetBoolArg("-discover", true); | fDiscover = gArgs.GetBoolArg("-discover", true); | ||||
g_relay_txes = !gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY); | g_relay_txes = !gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY); | ||||
for (const std::string &strAddr : gArgs.GetArgs("-externalip")) { | for (const std::string &strAddr : gArgs.GetArgs("-externalip")) { | ||||
CService addrLocal; | CService addrLocal; | ||||
if (Lookup(strAddr.c_str(), addrLocal, GetListenPort(), fNameLookup) && | if (Lookup(strAddr.c_str(), addrLocal, GetListenPort(), fNameLookup) && | ||||
addrLocal.IsValid()) { | addrLocal.IsValid()) { | ||||
AddLocal(addrLocal, LOCAL_MANUAL); | AddLocal(addrLocal, LOCAL_MANUAL); | ||||
} else { | } else { | ||||
return InitError(ResolveErrMsg("externalip", strAddr)); | return InitError( | ||||
Untranslated(ResolveErrMsg("externalip", strAddr))); | |||||
} | } | ||||
} | } | ||||
#if ENABLE_ZMQ | #if ENABLE_ZMQ | ||||
g_zmq_notification_interface = CZMQNotificationInterface::Create(); | g_zmq_notification_interface = CZMQNotificationInterface::Create(); | ||||
if (g_zmq_notification_interface) { | if (g_zmq_notification_interface) { | ||||
RegisterValidationInterface(g_zmq_notification_interface); | RegisterValidationInterface(g_zmq_notification_interface); | ||||
▲ Show 20 Lines • Show All 118 Lines • ▼ Show 20 Lines | while (!fLoaded && !ShutdownRequested()) { | ||||
} | } | ||||
// If the loaded chain has a wrong genesis, bail out immediately | // If the loaded chain has a wrong genesis, bail out immediately | ||||
// (we're likely using a testnet datadir, or the other way | // (we're likely using a testnet datadir, or the other way | ||||
// around). | // around). | ||||
if (!::BlockIndex().empty() && | if (!::BlockIndex().empty() && | ||||
!LookupBlockIndex(params.hashGenesisBlock)) { | !LookupBlockIndex(params.hashGenesisBlock)) { | ||||
return InitError(_("Incorrect or no genesis block found. " | return InitError(_("Incorrect or no genesis block found. " | ||||
"Wrong datadir for network?") | "Wrong datadir for network?")); | ||||
.translated); | |||||
} | } | ||||
// Check for changed -prune state. What we are concerned about | // Check for changed -prune state. What we are concerned about | ||||
// is a user who has pruned blocks in the past, but is now | // is a user who has pruned blocks in the past, but is now | ||||
// trying to run unpruned. | // trying to run unpruned. | ||||
if (fHavePruned && !fPruneMode) { | if (fHavePruned && !fPruneMode) { | ||||
strLoadError = | strLoadError = | ||||
_("You need to rebuild the database using -reindex to " | _("You need to rebuild the database using -reindex to " | ||||
▲ Show 20 Lines • Show All 121 Lines • ▼ Show 20 Lines | while (!fLoaded && !ShutdownRequested()) { | ||||
if (fRet) { | if (fRet) { | ||||
fReindex = true; | fReindex = true; | ||||
AbortShutdown(); | AbortShutdown(); | ||||
} else { | } else { | ||||
LogPrintf("Aborted block database rebuild. Exiting.\n"); | LogPrintf("Aborted block database rebuild. Exiting.\n"); | ||||
return false; | return false; | ||||
} | } | ||||
} else { | } else { | ||||
return InitError(strLoadError.translated); | return InitError(strLoadError); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// As LoadBlockIndex can take several minutes, it's possible the user | // As LoadBlockIndex can take several minutes, it's possible the user | ||||
// requested to kill the GUI during the last operation. If so, exit. | // requested to kill the GUI during the last operation. If so, exit. | ||||
// As the program has not fully started yet, Shutdown() is possibly | // As the program has not fully started yet, Shutdown() is possibly | ||||
// overkill. | // overkill. | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | if (fPruneMode) { | ||||
if (!fReindex) { | if (!fReindex) { | ||||
uiInterface.InitMessage(_("Pruning blockstore...").translated); | uiInterface.InitMessage(_("Pruning blockstore...").translated); | ||||
::ChainstateActive().PruneAndFlush(); | ::ChainstateActive().PruneAndFlush(); | ||||
} | } | ||||
} | } | ||||
// Step 11: import blocks | // Step 11: import blocks | ||||
if (!CheckDiskSpace(GetDataDir())) { | if (!CheckDiskSpace(GetDataDir())) { | ||||
InitError(strprintf(_("Error: Disk space is low for %s").translated, | InitError( | ||||
GetDataDir())); | strprintf(_("Error: Disk space is low for %s"), GetDataDir())); | ||||
return false; | return false; | ||||
} | } | ||||
if (!CheckDiskSpace(GetBlocksDir())) { | if (!CheckDiskSpace(GetBlocksDir())) { | ||||
InitError(strprintf(_("Error: Disk space is low for %s").translated, | InitError( | ||||
GetBlocksDir())); | strprintf(_("Error: Disk space is low for %s"), GetBlocksDir())); | ||||
return false; | return false; | ||||
} | } | ||||
// Either install a handler to notify us when genesis activates, or set | // Either install a handler to notify us when genesis activates, or set | ||||
// fHaveGenesis directly. | // fHaveGenesis directly. | ||||
// No locking, as this happens before any background thread is started. | // No locking, as this happens before any background thread is started. | ||||
boost::signals2::connection block_notify_genesis_wait_connection; | boost::signals2::connection block_notify_genesis_wait_connection; | ||||
if (::ChainActive().Tip() == nullptr) { | if (::ChainActive().Tip() == nullptr) { | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | #endif | ||||
connOptions.nMaxOutboundTimeframe = nMaxOutboundTimeframe; | connOptions.nMaxOutboundTimeframe = nMaxOutboundTimeframe; | ||||
connOptions.nMaxOutboundLimit = nMaxOutboundLimit; | connOptions.nMaxOutboundLimit = nMaxOutboundLimit; | ||||
connOptions.m_peer_connect_timeout = peer_connect_timeout; | connOptions.m_peer_connect_timeout = peer_connect_timeout; | ||||
for (const std::string &strBind : gArgs.GetArgs("-bind")) { | for (const std::string &strBind : gArgs.GetArgs("-bind")) { | ||||
CService addrBind; | CService addrBind; | ||||
if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false)) { | if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false)) { | ||||
return InitError(ResolveErrMsg("bind", strBind)); | return InitError(Untranslated(ResolveErrMsg("bind", strBind))); | ||||
} | } | ||||
connOptions.vBinds.push_back(addrBind); | connOptions.vBinds.push_back(addrBind); | ||||
} | } | ||||
for (const std::string &strBind : gArgs.GetArgs("-whitebind")) { | for (const std::string &strBind : gArgs.GetArgs("-whitebind")) { | ||||
NetWhitebindPermissions whitebind; | NetWhitebindPermissions whitebind; | ||||
std::string error; | std::string error; | ||||
if (!NetWhitebindPermissions::TryParse(strBind, whitebind, error)) { | if (!NetWhitebindPermissions::TryParse(strBind, whitebind, error)) { | ||||
return InitError(error); | return InitError(Untranslated(error)); | ||||
} | } | ||||
connOptions.vWhiteBinds.push_back(whitebind); | connOptions.vWhiteBinds.push_back(whitebind); | ||||
} | } | ||||
for (const auto &net : gArgs.GetArgs("-whitelist")) { | for (const auto &net : gArgs.GetArgs("-whitelist")) { | ||||
NetWhitelistPermissions subnet; | NetWhitelistPermissions subnet; | ||||
std::string error; | std::string error; | ||||
if (!NetWhitelistPermissions::TryParse(net, subnet, error)) { | if (!NetWhitelistPermissions::TryParse(net, subnet, error)) { | ||||
return InitError(error); | return InitError(Untranslated(error)); | ||||
} | } | ||||
connOptions.vWhitelistedRange.push_back(subnet); | connOptions.vWhitelistedRange.push_back(subnet); | ||||
} | } | ||||
connOptions.vSeedNodes = gArgs.GetArgs("-seednode"); | connOptions.vSeedNodes = gArgs.GetArgs("-seednode"); | ||||
// Initiate outbound connections unless connect=0 | // Initiate outbound connections unless connect=0 | ||||
connOptions.m_use_addrman_outgoing = !gArgs.IsArgSet("-connect"); | connOptions.m_use_addrman_outgoing = !gArgs.IsArgSet("-connect"); | ||||
Show All 32 Lines |