Skip to content
Closed
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
15 changes: 12 additions & 3 deletions src/bitcoin-cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ static int AppInitRPC(int argc, char* argv[])
return EXIT_FAILURE;
}
try {
gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME), false);
} catch (const std::exception& e) {
fprintf(stderr,"Error reading configuration file: %s\n", e.what());
return EXIT_FAILURE;
Expand All @@ -118,6 +118,16 @@ static int AppInitRPC(int argc, char* argv[])
fprintf(stderr, "Error: %s\n", e.what());
return EXIT_FAILURE;
}

if (!gArgs.IsArgSet("-conf")) {
try {
gArgs.ReadConfigFile(BITCOIN_NETCONF_FILENAME, true);
} catch (const std::exception& e) {
fprintf(stderr, "Error reading network configuration file: %s\n", e.what());
return EXIT_FAILURE;
}
}

if (gArgs.GetBoolArg("-rpcssl", false))
{
fprintf(stderr, "Error: SSL mode for RPC (-rpcssl) is no longer supported.\n");
Expand Down Expand Up @@ -317,8 +327,7 @@ static UniValue CallRPC(BaseRequestHandler *rh, const std::string& strMethod, co
if (!GetAuthCookie(&strRPCUserColonPass)) {
throw std::runtime_error(strprintf(
_("Could not locate RPC credentials. No authentication cookie could be found, and RPC password is not set. See -rpcpassword and -stdinrpcpass. Configuration file: (%s)"),
GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)).string().c_str()));

GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME), false).string().c_str()));
}
} else {
strRPCUserColonPass = gArgs.GetArg("-rpcuser", "") + ":" + gArgs.GetArg("-rpcpassword", "");
Expand Down
11 changes: 10 additions & 1 deletion src/bitcoind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ bool AppInit(int argc, char* argv[])
}
try
{
gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME), false);
} catch (const std::exception& e) {
fprintf(stderr,"Error reading configuration file: %s\n", e.what());
return false;
Expand All @@ -116,6 +116,15 @@ bool AppInit(int argc, char* argv[])
return false;
}

if (!gArgs.IsArgSet("-conf")) {
try {
gArgs.ReadConfigFile(BITCOIN_NETCONF_FILENAME, true);
} catch (const std::exception& e) {
fprintf(stderr, "Error reading network configuration file: %s\n", e.what());
return false;
}
}

// Error out when loose non-argument tokens are encountered on command line
for (int i = 1; i < argc; i++) {
if (!IsSwitchChar(argv[i][0])) {
Expand Down
5 changes: 4 additions & 1 deletion src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1215,7 +1215,10 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
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", GetDataDir().string());
LogPrintf("Using config file %s\n", GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)).string());
LogPrintf("Using config file %s\n", GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME), false).string());
if (!gArgs.IsArgSet("-conf")) {
LogPrintf("Using network config file %s\n", GetConfigFile(BITCOIN_NETCONF_FILENAME, true).string());
}
LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD);

InitSignatureCache();
Expand Down
12 changes: 11 additions & 1 deletion src/qt/bitcoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
try {
gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME), false);
} catch (const std::exception& e) {
QMessageBox::critical(0, QObject::tr(PACKAGE_NAME),
QObject::tr("Error: Cannot parse configuration file: %1. Only use key=value syntax.").arg(e.what()));
Expand Down Expand Up @@ -659,6 +659,16 @@ int main(int argc, char *argv[])
// Re-initialize translations after changing application name (language in network-specific settings can be different)
initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator);

if (!gArgs.IsArgSet("-conf")) {
try {
gArgs.ReadConfigFile(BITCOIN_NETCONF_FILENAME, true);
} catch (const std::exception& e) {
QMessageBox::critical(0, QObject::tr(PACKAGE_NAME),
QObject::tr("Error: Cannot parse network configuration file: %1. Only use key=value syntax.").arg(e.what()));
return EXIT_FAILURE;
}
}

#ifdef ENABLE_WALLET
/// 8. URI IPC sending
// - Do this early as we don't want to bother initializing if we are just calling IPC
Expand Down
2 changes: 1 addition & 1 deletion src/qt/guiutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ void openDebugLogfile()

bool openBitcoinConf()
{
boost::filesystem::path pathConfig = GetConfigFile(BITCOIN_CONF_FILENAME);
boost::filesystem::path pathConfig = GetConfigFile(BITCOIN_CONF_FILENAME, false);

/* Create the file */
boost::filesystem::ofstream configFile(pathConfig, std::ios_base::app);
Expand Down
9 changes: 5 additions & 4 deletions src/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
const int64_t nStartupTime = GetTime();

const char * const BITCOIN_CONF_FILENAME = "bitcoin.conf";
const char * const BITCOIN_NETCONF_FILENAME = "network.conf";
const char * const BITCOIN_PID_FILENAME = "bitcoind.pid";

ArgsManager gArgs;
Expand Down Expand Up @@ -590,18 +591,18 @@ void ClearDatadirCache()
pathCachedNetSpecific = fs::path();
}

fs::path GetConfigFile(const std::string& confPath)
fs::path GetConfigFile(const std::string& confPath, bool fNetSpecific)
{
fs::path pathConfigFile(confPath);
if (!pathConfigFile.is_complete())
pathConfigFile = GetDataDir(false) / pathConfigFile;
pathConfigFile = GetDataDir(fNetSpecific) / pathConfigFile;

return pathConfigFile;
}

void ArgsManager::ReadConfigFile(const std::string& confPath)
void ArgsManager::ReadConfigFile(const std::string& confPath, bool fNetSpecific)
{
fs::ifstream streamConfig(GetConfigFile(confPath));
fs::ifstream streamConfig(GetConfigFile(confPath, fNetSpecific));
if (!streamConfig.good())
return; // No bitcoin.conf file is OK

Expand Down
5 changes: 3 additions & 2 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ extern std::atomic<bool> fReopenDebugLog;
extern CTranslationInterface translationInterface;

extern const char * const BITCOIN_CONF_FILENAME;
extern const char * const BITCOIN_NETCONF_FILENAME;
extern const char * const BITCOIN_PID_FILENAME;

extern std::atomic<uint32_t> logCategories;
Expand Down Expand Up @@ -171,7 +172,7 @@ bool TryCreateDirectories(const fs::path& p);
fs::path GetDefaultDataDir();
const fs::path &GetDataDir(bool fNetSpecific = true);
void ClearDatadirCache();
fs::path GetConfigFile(const std::string& confPath);
fs::path GetConfigFile(const std::string& confPath, bool fNetSpecific);
#ifndef WIN32
fs::path GetPidFile();
void CreatePidFile(const fs::path &path, pid_t pid);
Expand Down Expand Up @@ -200,7 +201,7 @@ class ArgsManager
std::map<std::string, std::vector<std::string>> mapMultiArgs;
public:
void ParseParameters(int argc, const char*const argv[]);
void ReadConfigFile(const std::string& confPath);
void ReadConfigFile(const std::string& confPath, bool fNetSpecific);

/**
* Return a vector of strings of the given argument
Expand Down
86 changes: 86 additions & 0 deletions test/functional/netconf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/usr/bin/env python3
# Copyright (c) 2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Tests the network-specific config file."""

import os
from test_framework.test_framework import BitcoinTestFramework

class NetConfTest(BitcoinTestFramework):
def setup_chain(self):
super().setup_chain()

with open(os.path.join(self.options.tmpdir, "node0", "bitcoin-alt.conf"), 'a', encoding='utf8') as f:
for l in open(os.path.join(self.options.tmpdir, "node0", "bitcoin.conf")):
f.write(l)
f.write("uacomment=mainalt\n")
f.write("maxmempool=222\n")

with open(os.path.join(self.options.tmpdir, "node0", "bitcoin.conf"), 'a', encoding='utf8') as f:
f.write("uacomment=main\n")

def set_test_params(self):
self.setup_clean_chain = False
self.num_nodes = 1

def check_maxmempool(self, expected):
mpinfo = self.nodes[0].getmempoolinfo()
maxmem = mpinfo["maxmempool"]
assert maxmem == expected*1000000, "Max mempool is %s M not %s M" % (maxmem/1000000, expected)

def check_subversion(self, *expected):
nwinfo = self.nodes[0].getnetworkinfo()
subversion = nwinfo["subversion"]
want = "(testnode0; " + "; ".join(expected) + ")/"
assert subversion.endswith(want), "Subversion %s does not end with %s" % (subversion, want)

def run_test(self):
# expected behaviour:
# single option arguments should adopt the first seen value,
# in order of command line, bitcoin.conf, network.conf.
# tested using maxmempool setting.
#
# multi option arguments should see all values, in the same
# order (command line, bitcoin.conf, network.conf). tested
# using uacomment sub-version.

# works without network.conf
self.check_subversion("main")
self.check_maxmempool(300)

with open(os.path.join(self.options.tmpdir, "node0", "regtest", "network.conf"), "w", encoding="utf8") as f:
f.write("uacomment=net\n")
f.write("maxmempool=111\n")

# by default, loads network.conf
self.restart_node(0)
self.check_subversion("main", "net")
self.check_maxmempool(111)

# if conf is specified, network.conf is not loaded
self.restart_node(0, ["-conf=bitcoin-alt.conf"])
self.check_subversion("mainalt")
self.check_maxmempool(222)

# even if it's the same config file
self.restart_node(0, ["-conf=bitcoin.conf"])
self.check_subversion("main")
self.check_maxmempool(300)

# check network.conf doesn't override bitcoin.conf setting
with open(os.path.join(self.options.tmpdir, "node0", "bitcoin.conf"), 'a', encoding='utf8') as f:
f.write("maxmempool=333\n")

self.restart_node(0)
self.check_subversion("main", "net")
self.check_maxmempool(333)

# netconf on command line overrides specification in bitcoin.conf
self.restart_node(0, ["-uacomment=cmd", "-maxmempool=444"])
self.check_subversion("cmd", "main", "net")
self.check_maxmempool(444)

if __name__ == '__main__':
NetConfTest().main()

1 change: 1 addition & 0 deletions test/functional/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
'p2p-fingerprint.py',
'uacomment.py',
'p2p-acceptblock.py',
'netconf.py',
]

EXTENDED_SCRIPTS = [
Expand Down