Skip to content

Commit 1988cfa

Browse files
committed
Implement changesettings
1 parent 352716f commit 1988cfa

File tree

4 files changed

+141
-4
lines changed

4 files changed

+141
-4
lines changed

src/rpc/misc.cpp

+137
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,140 @@ UniValue listsettings(const UniValue& params, bool fHelp)
9696
return gArgs.OutputArgs();
9797
}
9898

99+
UniValue changesettings(const UniValue& params, bool fHelp)
100+
{
101+
if (fHelp || params.size() < 1)
102+
{
103+
throw runtime_error(
104+
"changesettings <name=value> [name=value] ... [name=value]\n"
105+
"\n"
106+
"name=value: name and value pair for setting to store/change (1st mandatory, 2nd+ optional).\n"
107+
"\n"
108+
"Note that the settings should be done in the same format as config file entries.\n"
109+
"\n"
110+
"Example:"
111+
"changesettings enable enablestakesplit=1 stakingefficiency=98 minstakesplitvalue=800\n"
112+
);
113+
}
114+
115+
// -------- name ------------ value - value_changed - immediate_effect
116+
std::map<std::string, std::tuple<std::string, bool, bool>> valid_settings;
117+
118+
UniValue result(UniValue::VOBJ);
119+
UniValue settings_stored_with_no_state_change(UniValue::VARR);
120+
UniValue settings_immediate(UniValue::VARR);
121+
UniValue settings_applied_requiring_restart(UniValue::VARR);
122+
//UniValue invalid_settings_ignored(UniValue::VARR);
123+
124+
// Validation
125+
for (unsigned int i = 0; i < params.size(); ++i)
126+
{
127+
std::string param = params[i].get_str();
128+
129+
if (param.size() > 0 && param[0] == '-')
130+
{
131+
throw JSONRPCError(RPC_INVALID_PARAMETER, "Incorrectly formatted setting change: " + param);
132+
}
133+
134+
std::string::size_type pos;
135+
std::string name;
136+
std::string value;
137+
138+
if ((pos = param.find('=')) != std::string::npos)
139+
{
140+
name = param.substr(0, pos);
141+
value = param.substr(pos + 1);
142+
}
143+
else
144+
{
145+
throw JSONRPCError(RPC_INVALID_PARAMETER, "Incorrectly formatted setting change: " + param);
146+
}
147+
148+
std::optional<unsigned int> flags = gArgs.GetArgFlags('-' + name);
149+
150+
if (!flags)
151+
{
152+
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid setting: " + param);
153+
}
154+
155+
// TODO: Record explicit default state for settings.
156+
// This currently has a problem that I am not sure yet how to solve. Settings that are defaulted to true, unless
157+
// they are set to the contrary, such as -staking, will falsely indicate a change because the defaulted state is
158+
// not explicitly stored for comparison. After there is an explicit entry defined in the settings file, it works
159+
// correctly.
160+
161+
// Also, the overloading of GetArg is NOT helpful here...
162+
std::string current_value;
163+
164+
// It is either a string or a number.... One of these will succeed.
165+
try
166+
{
167+
current_value = gArgs.GetArg(name, "never_used_default");
168+
}
169+
catch (std::exception& e)
170+
{
171+
// If it is a number convert back to a string.
172+
current_value = ToString(gArgs.GetArg(name, 1));
173+
}
174+
175+
bool value_changed = (current_value != value);
176+
bool immediate_effect = *flags & ArgsManager::IMMEDIATE_EFFECT;
177+
178+
auto insert_pair = valid_settings.insert(std::make_pair(
179+
name, std::make_tuple(value, value_changed, immediate_effect)));
180+
181+
if (!insert_pair.second)
182+
{
183+
throw JSONRPCError(RPC_INVALID_PARAMETER, "changesettings does not support more than one instance of the same "
184+
"setting: " + param);
185+
}
186+
}
187+
188+
// Now that validation is done do the update work.
189+
bool restart_required = false;
190+
191+
for (const auto& setting : valid_settings)
192+
{
193+
const std::string& name = setting.first;
194+
const std::string& value = std::get<0>(setting.second);
195+
const bool& value_changed = std::get<1>(setting.second);
196+
const bool& immediate_effect = std::get<2>(setting.second);
197+
198+
std::string param = name + "=" + value;
199+
200+
// Regardless, store in r-w settings file.
201+
if (!updateRwSetting(name, value))
202+
{
203+
throw JSONRPCError(RPC_MISC_ERROR, "Error storing setting in read-write settings file.");
204+
}
205+
206+
if (value_changed)
207+
{
208+
gArgs.ForceSetArg(name, value);
209+
210+
if (immediate_effect)
211+
{
212+
settings_immediate.push_back(param);
213+
}
214+
else
215+
{
216+
settings_applied_requiring_restart.push_back(param);
217+
218+
// Record if restart required.
219+
restart_required |= !immediate_effect;
220+
}
221+
}
222+
else
223+
{
224+
settings_stored_with_no_state_change.push_back(param);
225+
}
226+
}
227+
228+
result.pushKV("settings_change_requires_restart", restart_required);
229+
result.pushKV("settings_stored_with_no_state_change", settings_stored_with_no_state_change);
230+
result.pushKV("settings_changed_taking_immediate_effect", settings_immediate);
231+
result.pushKV("settings_changed_requiring_restart", settings_applied_requiring_restart);
232+
233+
return result;
234+
}
235+

src/rpc/server.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ static const CRPCCommand vRPCCommands[] =
366366
{ "auditsnapshotaccrual", &auditsnapshotaccrual, cat_developer },
367367
{ "auditsnapshotaccruals", &auditsnapshotaccruals, cat_developer },
368368
{ "addkey", &addkey, cat_developer },
369+
{ "changesettings", &changesettings, cat_developer },
369370
{ "currentcontractaverage", &currentcontractaverage, cat_developer },
370371
{ "debug", &debug, cat_developer },
371372
{ "dumpcontracts", &dumpcontracts, cat_developer },

src/rpc/server.h

+1
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ extern UniValue scraperreport(const UniValue& params, bool fHelp);
221221
// Network
222222
extern UniValue addnode(const UniValue& params, bool fHelp);
223223
extern UniValue askforoutstandingblocks(const UniValue& params, bool fHelp);
224+
extern UniValue changesettings(const UniValue& params, bool fHelp);
224225
extern UniValue clearbanned(const UniValue& params, bool fHelp);
225226
extern UniValue currenttime(const UniValue& params, bool fHelp);
226227
extern UniValue getaddednodeinfo(const UniValue& params, bool fHelp);

src/util/system.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -1038,7 +1038,7 @@ UniValue ArgsManager::OutputArgsSection(
10381038
setting.pushKV(arg.first, value);
10391039
}
10401040

1041-
setting.pushKV("changeable_without_restart", (*flags & IMMEDIATE_EFFECT) ? "true" : "false");
1041+
setting.pushKV("changeable_without_restart", (bool)(*flags & IMMEDIATE_EFFECT));
10421042

10431043
settings.push_back(setting);
10441044
}
@@ -1086,7 +1086,7 @@ UniValue ArgsManager::OutputArgs() const
10861086

10871087
arg.pushKV(setting.first, setting.second);
10881088

1089-
arg.pushKV("changeable_without_restart", (*flags & IMMEDIATE_EFFECT) ? "true" : "false");
1089+
arg.pushKV("changeable_without_restart", (bool)(*flags & IMMEDIATE_EFFECT));
10901090

10911091
settings.push_back(arg);
10921092
}
@@ -1263,5 +1263,3 @@ std::pair<int, char**> WinCmdLineArgs::get()
12631263
}
12641264
#endif
12651265
} // namespace util
1266-
1267-

0 commit comments

Comments
 (0)