Skip to content

Commit 0e55bc6

Browse files
committed
settings: Add update/getPersistent/isIgnored methods
Add interfaces::Node methods to give GUI finer grained control over settings.json file. Update method is used to write settings to the file, getPersistent and isIgnored methods are used to find out about settings file and command line option interactions.
1 parent 0de3694 commit 0e55bc6

File tree

7 files changed

+101
-10
lines changed

7 files changed

+101
-10
lines changed

src/interfaces/node.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
#ifndef BITCOIN_INTERFACES_NODE_H
66
#define BITCOIN_INTERFACES_NODE_H
77

8-
#include <consensus/amount.h>
9-
#include <net.h> // For NodeId
10-
#include <net_types.h> // For banmap_t
11-
#include <netaddress.h> // For Network
12-
#include <netbase.h> // For ConnectionDirection
8+
#include <consensus/amount.h> // For CAmount
9+
#include <net.h> // For NodeId
10+
#include <net_types.h> // For banmap_t
11+
#include <netaddress.h> // For Network
12+
#include <netbase.h> // For ConnectionDirection
1313
#include <support/allocators/secure.h> // For SecureString
14+
#include <util/settings.h> // For util::SettingsValue
1415
#include <util/translation.h>
1516

1617
#include <functional>
@@ -97,6 +98,20 @@ class Node
9798
//! Return whether shutdown was requested.
9899
virtual bool shutdownRequested() = 0;
99100

101+
//! Return whether a particular setting in <datadir>/settings.json is or
102+
//! would be ignored because it is also specified in the command line.
103+
virtual bool isSettingIgnored(const std::string& name) = 0;
104+
105+
//! Return setting value from <datadir>/settings.json or bitcoin.conf.
106+
virtual util::SettingsValue getPersistentSetting(const std::string& name) = 0;
107+
108+
//! Update a setting in <datadir>/settings.json.
109+
virtual void updateRwSetting(const std::string& name, const util::SettingsValue& value) = 0;
110+
111+
//! Force a setting value to be applied, overriding any other configuration
112+
//! source, but not being persisted.
113+
virtual void forceSetting(const std::string& name, const util::SettingsValue& value) = 0;
114+
100115
//! Map port.
101116
virtual void mapPort(bool use_upnp, bool use_natpmp) = 0;
102117

src/node/interfaces.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,38 @@ class NodeImpl : public Node
112112
}
113113
}
114114
bool shutdownRequested() override { return ShutdownRequested(); }
115+
bool isSettingIgnored(const std::string& name) override
116+
{
117+
bool ignored = false;
118+
gArgs.LockSettings([&](util::Settings& settings) {
119+
if (auto* options = util::FindKey(settings.command_line_options, name)) {
120+
ignored = !options->empty();
121+
}
122+
});
123+
return ignored;
124+
}
125+
util::SettingsValue getPersistentSetting(const std::string& name) override { return gArgs.GetPersistentSetting(name); }
126+
void updateRwSetting(const std::string& name, const util::SettingsValue& value) override
127+
{
128+
gArgs.LockSettings([&](util::Settings& settings) {
129+
if (value.isNull()) {
130+
settings.rw_settings.erase(name);
131+
} else {
132+
settings.rw_settings[name] = value;
133+
}
134+
});
135+
gArgs.WriteSettingsFile();
136+
}
137+
void forceSetting(const std::string& name, const util::SettingsValue& value) override
138+
{
139+
gArgs.LockSettings([&](util::Settings& settings) {
140+
if (value.isNull()) {
141+
settings.forced_settings.erase(name);
142+
} else {
143+
settings.forced_settings[name] = value;
144+
}
145+
});
146+
}
115147
void mapPort(bool use_upnp, bool use_natpmp) override { StartMapPort(use_upnp, use_natpmp); }
116148
bool getProxy(Network net, Proxy& proxy_info) override { return GetProxy(net, proxy_info); }
117149
size_t getNodeCount(ConnectionDirection flags) override

src/test/settings_tests.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ BOOST_AUTO_TEST_CASE(ReadWrite)
105105
//! Check settings struct contents against expected json strings.
106106
static void CheckValues(const util::Settings& settings, const std::string& single_val, const std::string& list_val)
107107
{
108-
util::SettingsValue single_value = GetSetting(settings, "section", "name", false, false);
108+
util::SettingsValue single_value = GetSetting(settings, "section", "name", false, false, false);
109109
util::SettingsValue list_value(util::SettingsValue::VARR);
110110
for (const auto& item : GetSettingsList(settings, "section", "name", false)) {
111111
list_value.push_back(item);
@@ -141,9 +141,9 @@ BOOST_AUTO_TEST_CASE(NullOverride)
141141
{
142142
util::Settings settings;
143143
settings.command_line_options["name"].push_back("value");
144-
BOOST_CHECK_EQUAL(R"("value")", GetSetting(settings, "section", "name", false, false).write().c_str());
144+
BOOST_CHECK_EQUAL(R"("value")", GetSetting(settings, "section", "name", false, false, false).write().c_str());
145145
settings.forced_settings["name"] = {};
146-
BOOST_CHECK_EQUAL(R"(null)", GetSetting(settings, "section", "name", false, false).write().c_str());
146+
BOOST_CHECK_EQUAL(R"(null)", GetSetting(settings, "section", "name", false, false, false).write().c_str());
147147
}
148148

149149
// Test different ways settings can be merged, and verify results. This test can
@@ -224,7 +224,7 @@ BOOST_FIXTURE_TEST_CASE(Merge, MergeTestingSetup)
224224
}
225225

226226
desc += " || ";
227-
desc += GetSetting(settings, network, name, ignore_default_section_config, /* get_chain_name= */ false).write();
227+
desc += GetSetting(settings, network, name, ignore_default_section_config, /*ignore_nonpersistent=*/false, /*get_chain_name=*/false).write();
228228
desc += " |";
229229
for (const auto& s : GetSettingsList(settings, network, name, ignore_default_section_config)) {
230230
desc += " ";

src/util/settings.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ SettingsValue GetSetting(const Settings& settings,
127127
const std::string& section,
128128
const std::string& name,
129129
bool ignore_default_section_config,
130+
bool ignore_nonpersistent,
130131
bool get_chain_name)
131132
{
132133
SettingsValue result;
@@ -162,6 +163,9 @@ SettingsValue GetSetting(const Settings& settings,
162163
return;
163164
}
164165

166+
// Ignore nonpersistent settings if requested.
167+
if (ignore_nonpersistent && (source == Source::COMMAND_LINE || source == Source::FORCED)) return;
168+
165169
// Skip negated command line settings.
166170
if (skip_negated_command_line && span.last_negated()) return;
167171

src/util/settings.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,18 @@ bool WriteSettings(const fs::path& path,
5555
//! @param ignore_default_section_config - ignore values in the default section
5656
//! of the config file (part before any
5757
//! [section] keywords)
58+
//! @param ignore_nonpersistent - ignore non-persistent settings values (forced
59+
//! settings values and values specified on the
60+
//! command line). Only return settings in the
61+
//! read-only config and read-write settings
62+
//! files.
5863
//! @param get_chain_name - enable special backwards compatible behavior
5964
//! for GetChainName
6065
SettingsValue GetSetting(const Settings& settings,
6166
const std::string& section,
6267
const std::string& name,
6368
bool ignore_default_section_config,
69+
bool ignore_nonpersistent,
6470
bool get_chain_name);
6571

6672
//! Get combined setting value similar to GetSetting(), except if setting was

src/util/system.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,13 @@ bool ArgsManager::WriteSettingsFile(std::vector<std::string>* errors) const
592592
return true;
593593
}
594594

595+
util::SettingsValue ArgsManager::GetPersistentSetting(const std::string& name) const
596+
{
597+
LOCK(cs_args);
598+
return util::GetSetting(m_settings, m_network, name, !UseDefaultSection("-" + name),
599+
/*ignore_nonpersistent=*/true, /*get_chain_name=*/false);
600+
}
601+
595602
bool ArgsManager::IsArgNegated(const std::string& strArg) const
596603
{
597604
return GetSetting(strArg).isFalse();
@@ -600,18 +607,33 @@ bool ArgsManager::IsArgNegated(const std::string& strArg) const
600607
std::string ArgsManager::GetArg(const std::string& strArg, const std::string& strDefault) const
601608
{
602609
const util::SettingsValue value = GetSetting(strArg);
610+
return SettingToString(value, strDefault);
611+
}
612+
613+
std::string SettingToString(const util::SettingsValue& value, const std::string& strDefault)
614+
{
603615
return value.isNull() ? strDefault : value.isFalse() ? "0" : value.isTrue() ? "1" : value.isNum() ? value.getValStr() : value.get_str();
604616
}
605617

606618
int64_t ArgsManager::GetIntArg(const std::string& strArg, int64_t nDefault) const
607619
{
608620
const util::SettingsValue value = GetSetting(strArg);
621+
return SettingToInt(value, nDefault);
622+
}
623+
624+
int64_t SettingToInt(const util::SettingsValue& value, int64_t nDefault)
625+
{
609626
return value.isNull() ? nDefault : value.isFalse() ? 0 : value.isTrue() ? 1 : value.isNum() ? value.getInt<int64_t>() : LocaleIndependentAtoi<int64_t>(value.get_str());
610627
}
611628

612629
bool ArgsManager::GetBoolArg(const std::string& strArg, bool fDefault) const
613630
{
614631
const util::SettingsValue value = GetSetting(strArg);
632+
return SettingToBool(value, fDefault);
633+
}
634+
635+
bool SettingToBool(const util::SettingsValue& value, bool fDefault)
636+
{
615637
return value.isNull() ? fDefault : value.isBool() ? value.get_bool() : InterpretBool(value.get_str());
616638
}
617639

@@ -1002,6 +1024,7 @@ std::string ArgsManager::GetChainName() const
10021024
LOCK(cs_args);
10031025
util::SettingsValue value = util::GetSetting(m_settings, /* section= */ "", SettingName(arg),
10041026
/* ignore_default_section_config= */ false,
1027+
/*ignore_nonpersistent=*/false,
10051028
/* get_chain_name= */ true);
10061029
return value.isNull() ? false : value.isBool() ? value.get_bool() : InterpretBool(value.get_str());
10071030
};
@@ -1034,7 +1057,8 @@ util::SettingsValue ArgsManager::GetSetting(const std::string& arg) const
10341057
{
10351058
LOCK(cs_args);
10361059
return util::GetSetting(
1037-
m_settings, m_network, SettingName(arg), !UseDefaultSection(arg), /* get_chain_name= */ false);
1060+
m_settings, m_network, SettingName(arg), !UseDefaultSection(arg),
1061+
/*ignore_nonpersistent=*/false, /*get_chain_name=*/false);
10381062
}
10391063

10401064
std::vector<util::SettingsValue> ArgsManager::GetSettingsList(const std::string& arg) const

src/util/system.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,10 @@ struct SectionInfo
161161
int m_line;
162162
};
163163

164+
std::string SettingToString(const util::SettingsValue&, const std::string&);
165+
int64_t SettingToInt(const util::SettingsValue&, int64_t);
166+
bool SettingToBool(const util::SettingsValue&, bool);
167+
164168
class ArgsManager
165169
{
166170
public:
@@ -448,6 +452,12 @@ class ArgsManager
448452
*/
449453
bool WriteSettingsFile(std::vector<std::string>* errors = nullptr) const;
450454

455+
/**
456+
* Get current setting from config file or read/write settings file,
457+
* ignoring nonpersistent command line or forced settings values.
458+
*/
459+
util::SettingsValue GetPersistentSetting(const std::string& name) const;
460+
451461
/**
452462
* Access settings with lock held.
453463
*/

0 commit comments

Comments
 (0)