From ef61d6a88fdf35ca78c545cfbde7c17be3d159e2 Mon Sep 17 00:00:00 2001 From: jamescowens Date: Sat, 5 Jun 2021 21:46:44 -0400 Subject: [PATCH 1/4] Implement GUI settings for stakesplitting This commit builds on the implementation of the ArgsManager and implements GUi settings in a new staking tab in the options dialog to dynamically control the status of stake splitting for staking optimization, and the associated settings, the staking efficiency and the minimum post stake split UTXO value. Validation is performed on the fields to ensure that the efficiency is between 75% and 98%, and the minstakesplitvalue is 800 or greater. Note that we are making use of the new updateRwSetting implemented with the ArgsManager port, which saves runtime settings to a read-write JSON settings file. Settings in this file take precedence over the read-only settings in the config file. The tool tips warn the user about this order-of-precedence (override), so they are not confused later. This also includes a check-box to disable/enable staking. --- src/gridcoin/staking/status.cpp | 1 + src/gridcoin/staking/status.h | 1 + src/init.cpp | 10 +-- src/miner.cpp | 11 ++- src/net.cpp | 8 +- src/qt/bitcoingui.cpp | 18 +++-- src/qt/forms/optionsdialog.ui | 86 ++++++++++++++++++++- src/qt/optionsdialog.cpp | 128 ++++++++++++++++++++++++++++++-- src/qt/optionsdialog.h | 7 ++ src/qt/optionsmodel.cpp | 38 ++++++++++ src/qt/optionsmodel.h | 6 +- src/util/system.h | 3 +- 12 files changed, 289 insertions(+), 28 deletions(-) diff --git a/src/gridcoin/staking/status.cpp b/src/gridcoin/staking/status.cpp index df3578c343..5f1f718545 100644 --- a/src/gridcoin/staking/status.cpp +++ b/src/gridcoin/staking/status.cpp @@ -18,6 +18,7 @@ namespace { //! constexpr const char* STAKING_ERROR_STRINGS[] { "None", + "Commanded disabled", "No Mature Coins", "No coins", "Entire balance reserved", diff --git a/src/gridcoin/staking/status.h b/src/gridcoin/staking/status.h index a097226ae9..1c2728d1c6 100644 --- a/src/gridcoin/staking/status.h +++ b/src/gridcoin/staking/status.h @@ -20,6 +20,7 @@ class MinerStatus enum ReasonNotStakingCategory { NONE, + COMMANDED_DISABLED, NO_MATURE_COINS, NO_COINS, ENTIRE_BALANCE_RESERVED, diff --git a/src/init.cpp b/src/init.cpp index 03d6e10ab2..7c3e53aea6 100755 --- a/src/init.cpp +++ b/src/init.cpp @@ -357,9 +357,9 @@ void SetupServerArgs() // Staking argsman.AddArg("-enablesidestaking", "Enable side staking functionality (default: 0)", - ArgsManager::ALLOW_ANY, OptionsCategory::STAKING); + ArgsManager::ALLOW_ANY | ArgsManager::IMMEDIATE_EFFECT, OptionsCategory::STAKING); argsman.AddArg("-staking", "Allow wallet to stake if conditions to stake are met (default: 1)", - ArgsManager::ALLOW_ANY, OptionsCategory::STAKING); + ArgsManager::ALLOW_ANY | ArgsManager::IMMEDIATE_EFFECT, OptionsCategory::STAKING); argsman.AddArg("-sidestake=", "Sidestake destination and allocation entry. There can be as many " "specified as desired. Only six per stake can be sent. If more than " "six are specified. Six are randomly chosen for each stake. Only active " @@ -367,13 +367,13 @@ void SetupServerArgs() ArgsManager::ALLOW_ANY, OptionsCategory::STAKING); argsman.AddArg("-enablestakesplit", "Enable unspent output spitting when staking to optimize staking efficiency " "(default: 0", - ArgsManager::ALLOW_ANY, OptionsCategory::STAKING); + ArgsManager::ALLOW_ANY | ArgsManager::IMMEDIATE_EFFECT, OptionsCategory::STAKING); argsman.AddArg("-stakingefficiency=", "Specify target staking efficiency for stake splitting (default: 90, " "clamped to [75, 98])", - ArgsManager::ALLOW_ANY, OptionsCategory::STAKING); + ArgsManager::ALLOW_ANY | ArgsManager::IMMEDIATE_EFFECT, OptionsCategory::STAKING); argsman.AddArg("-minstakesplitvalue=", strprintf("Specify minimum output value for post split output when stake " "splitting (default: %" PRId64 "GRC)", MIN_STAKE_SPLIT_VALUE_GRC), - ArgsManager::ALLOW_ANY, OptionsCategory::STAKING); + ArgsManager::ALLOW_ANY | ArgsManager::IMMEDIATE_EFFECT, OptionsCategory::STAKING); // Scraper argsman.AddArg("-scraper", "Activate scraper for statistics downloads. This will only work if the node has a wallet " diff --git a/src/miner.cpp b/src/miner.cpp index 55e5b02061..443b914397 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1156,14 +1156,14 @@ bool IsMiningAllowed(CWallet *pwallet) { bool status = true; - if(pwallet->IsLocked()) + if (pwallet->IsLocked()) { LOCK(g_miner_status.lock); g_miner_status.SetReasonNotStaking(GRC::MinerStatus::WALLET_LOCKED); status = false; } - if(fDevbuildCripple) + if (fDevbuildCripple) { LOCK(g_miner_status.lock); g_miner_status.SetReasonNotStaking(GRC::MinerStatus::TESTNET_ONLY); @@ -1177,6 +1177,13 @@ bool IsMiningAllowed(CWallet *pwallet) status = false; } + if (!gArgs.GetBoolArg("-staking", true)) + { + LOCK(g_miner_status.lock); + g_miner_status.SetReasonNotStaking(GRC::MinerStatus::COMMANDED_DISABLED); + status = false; + } + return status; } diff --git a/src/net.cpp b/src/net.cpp index 88bedb2c72..3b8a985857 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2032,12 +2032,8 @@ void StartNode(void* parg) if (!netThreads->createThread(ThreadDumpAddress,NULL,"ThreadDumpAddress")) LogPrintf("Error: createThread(ThreadDumpAddress) failed"); - // Mine proof-of-stake blocks in the background - if (!gArgs.GetBoolArg("-staking", true)) - LogPrintf("Staking disabled"); - else - if (!netThreads->createThread(ThreadStakeMiner,pwalletMain,"ThreadStakeMiner")) - LogPrintf("Error: createThread(ThreadStakeMiner) failed"); + if (!netThreads->createThread(ThreadStakeMiner,pwalletMain,"ThreadStakeMiner")) + LogPrintf("Error: createThread(ThreadStakeMiner) failed"); } bool StopNode() diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index d6776852cc..fabbf9f362 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -691,16 +691,22 @@ void BitcoinGUI::createToolBars() //12-21-2015 Prevent Lock from falling off the page frameBlocksLayout->addStretch(); + QTimer *timerStakingIcon = new QTimer(labelStakingIcon); + connect(timerStakingIcon, SIGNAL(timeout()), this, SLOT(updateStakingIcon())); + timerStakingIcon->start(MODEL_UPDATE_DELAY); + + // Instead of calling updateStakingIcon here, simply set the icon to staking off. + // This is to prevent problems since this GUI code can initialize before the core. + labelStakingIcon->setPixmap(GRC::ScaleStatusIcon(this, ":/icons/status_staking_no_" + sSheet)); + if (gArgs.GetBoolArg("-staking", true)) { - QTimer *timerStakingIcon = new QTimer(labelStakingIcon); - connect(timerStakingIcon, SIGNAL(timeout()), this, SLOT(updateStakingIcon())); - timerStakingIcon->start(MODEL_UPDATE_DELAY); - // Instead of calling updateStakingIcon here, simply set the icon to staking off. - // This is to prevent problems since this GUI code can initialize before the core. - labelStakingIcon->setPixmap(GRC::ScaleStatusIcon(this, ":/icons/status_staking_no_" + sSheet)); labelStakingIcon->setToolTip(tr("Not staking: Miner is not initialized.")); } + else + { + labelStakingIcon->setToolTip(tr("Not staking: Commanded disabled.")); + } statusBar()->addPermanentWidget(frameBlocks); diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index 43bbb533f0..a8ac9b801b 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -6,8 +6,8 @@ 0 0 - 540 - 400 + 709 + 421 @@ -254,6 +254,88 @@ + + + Staking + + + + + 10 + 10 + 651 + 135 + + + + + + + This enables or disables staking (the default is enabled). Note that a change to this setting will permanently override the config file with an entry in the settings file. + + + Enable Staking + + + + + + + This enables or disables splitting of stake outputs to optimize staking (default disabled). Note that a change to this setting will permanently override the config file with an entry in the settings file. + + + Enable Stake Splitting + + + + + + + + + Target Efficiency + + + + + + + Valid values are between 75 and 98 percent. Note that a change to this setting will permanently override the config file with an entry in the settings file. + + + + + + + Min Post Split UTXO + + + + + + + Valid values are 800 or greater. Note that a change to this setting will permanently override the config file with an entry in the settings file. + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + &Window diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 2d85a2a12f..42c4b7a471 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -6,6 +6,7 @@ #include "monitoreddatamapper.h" #include "optionsmodel.h" #include "init.h" +#include "miner.h" #include #include @@ -45,6 +46,8 @@ OptionsDialog::OptionsDialog(QWidget *parent) : connect(ui->connectSocks, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning_Proxy())); ui->proxyIp->installEventFilter(this); + ui->stakingEfficiency->installEventFilter(this); + ui->minPostSplitOutputValue->installEventFilter(this); /* Window elements init */ #ifdef Q_OS_MAC @@ -86,8 +89,13 @@ OptionsDialog::OptionsDialog(QWidget *parent) : connect(mapper, SIGNAL(viewModified()), this, SLOT(enableApplyButton())); /* disable apply button when new data loaded */ connect(mapper, SIGNAL(currentIndexChanged(int)), this, SLOT(disableApplyButton())); - /* setup/change UI elements when proxy IP is invalid/valid */ - connect(this, SIGNAL(proxyIpValid(QValidatedLineEdit *, bool)), this, SLOT(handleProxyIpValid(QValidatedLineEdit *, bool))); + /* setup/change UI elements when proxy IP, stakingEfficiency, or minStakeSplitValue is invalid/valid */ + connect(this, SIGNAL(proxyIpValid(QValidatedLineEdit *, bool)), + this, SLOT(handleProxyIpValid(QValidatedLineEdit *, bool))); + connect(this, SIGNAL(stakingEfficiencyValid(QValidatedLineEdit *, bool)), + this, SLOT(handleStakingEfficiencyValid(QValidatedLineEdit *, bool))); + connect(this, SIGNAL(minStakeSplitValueValid(QValidatedLineEdit *, bool)), + this, SLOT(handleMinStakeSplitValueValid(QValidatedLineEdit *, bool))); if (fTestNet) ui->disableUpdateCheck->setHidden(true); @@ -98,6 +106,15 @@ OptionsDialog::OptionsDialog(QWidget *parent) : connect(ui->gridcoinAtStartupMinimised, SIGNAL(toggled(bool)), this, SLOT(hideStartMinimized())); connect(ui->limitTxnDisplayCheckBox, SIGNAL(toggled(bool)), this, SLOT(hideLimitTxnDisplayDate())); + + bool stake_split_enabled = ui->enableStakeSplit->isChecked(); + + ui->stakingEfficiencyLabel->setHidden(!stake_split_enabled); + ui->stakingEfficiency->setHidden(!stake_split_enabled); + ui->minPostSplitOutputValueLabel->setHidden(!stake_split_enabled); + ui->minPostSplitOutputValue->setHidden(!stake_split_enabled); + + connect(ui->enableStakeSplit, SIGNAL(toggled(bool)), this, SLOT(hideStakeSplitting())); } OptionsDialog::~OptionsDialog() @@ -146,6 +163,12 @@ void OptionsDialog::setMapper() mapper->addMapping(ui->proxyPort, OptionsModel::ProxyPort); mapper->addMapping(ui->socksVersion, OptionsModel::ProxySocksVersion); + /* Staking */ + mapper->addMapping(ui->enableStaking, OptionsModel::EnableStaking); + mapper->addMapping(ui->enableStakeSplit, OptionsModel::EnableStakeSplit); + mapper->addMapping(ui->stakingEfficiency, OptionsModel::StakingEfficiency); + mapper->addMapping(ui->minPostSplitOutputValue, OptionsModel::MinStakeSplitValue); + /* Window */ mapper->addMapping(ui->disableTransactionNotifications, OptionsModel::DisableTrxNotifications); mapper->addMapping(ui->disablePollNotifications, OptionsModel::DisablePollNotifications); @@ -264,12 +287,25 @@ void OptionsDialog::hideLimitTxnDisplayDate() } } +void OptionsDialog::hideStakeSplitting() +{ + if (model) + { + bool stake_split_enabled = ui->enableStakeSplit->isChecked(); + + ui->stakingEfficiencyLabel->setHidden(!stake_split_enabled); + ui->stakingEfficiency->setHidden(!stake_split_enabled); + ui->minPostSplitOutputValueLabel->setHidden(!stake_split_enabled); + ui->minPostSplitOutputValue->setHidden(!stake_split_enabled); + } +} + void OptionsDialog::handleProxyIpValid(QValidatedLineEdit *object, bool fState) { // this is used in a check before re-enabling the save buttons fProxyIpValid = fState; - if(fProxyIpValid) + if (fProxyIpValid) { enableSaveButtons(); ui->statusLabel->clear(); @@ -283,16 +319,98 @@ void OptionsDialog::handleProxyIpValid(QValidatedLineEdit *object, bool fState) } } +void OptionsDialog::handleStakingEfficiencyValid(QValidatedLineEdit *object, bool fState) +{ + // this is used in a check before re-enabling the save buttons + fStakingEfficiencyValid = fState; + + if (fStakingEfficiencyValid) + { + enableSaveButtons(); + ui->statusLabel->clear(); + } + else + { + disableSaveButtons(); + object->setValid(fStakingEfficiencyValid); + ui->statusLabel->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel->setText(tr("The supplied target staking efficiency is invalid.")); + } +} + +void OptionsDialog::handleMinStakeSplitValueValid(QValidatedLineEdit *object, bool fState) +{ + // this is used in a check before re-enabling the save buttons + fMinStakeSplitValueValid = fState; + + if (fMinStakeSplitValueValid) + { + enableSaveButtons(); + ui->statusLabel->clear(); + } + else + { + disableSaveButtons(); + object->setValid(fMinStakeSplitValueValid); + ui->statusLabel->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel->setText(tr("The supplied minimum post stake-split UTXO size is invalid.")); + } +} + bool OptionsDialog::eventFilter(QObject *object, QEvent *event) { - if(event->type() == QEvent::FocusOut) + if (event->type() == QEvent::FocusOut) { - if(object == ui->proxyIp) + if (object == ui->proxyIp) { CService addr; /* Check proxyIp for a valid IPv4/IPv6 address and emit the proxyIpValid signal */ emit proxyIpValid(ui->proxyIp, LookupNumeric(ui->proxyIp->text().toStdString().c_str(), addr)); } + + if (object == ui->stakingEfficiency) + { + bool ok = false; + double efficiency = ui->stakingEfficiency->text().toDouble(&ok); + + if (!ok) + { + emit stakingEfficiencyValid(ui->stakingEfficiency, false); + } + else + { + if (efficiency < 75.0 || efficiency > 98.0) + { + emit stakingEfficiencyValid(ui->stakingEfficiency, false); + } + else + { + emit stakingEfficiencyValid(ui->stakingEfficiency, true); + } + } + } + + if (object == ui->minPostSplitOutputValue) + { + bool ok = false; + CAmount post_split_min_value = (CAmount) ui->minPostSplitOutputValue->text().toULong(&ok) * COIN; + + if (!ok) + { + emit minStakeSplitValueValid(ui->minPostSplitOutputValue, false); + } + else + { + if (post_split_min_value < MIN_STAKE_SPLIT_VALUE_GRC * COIN || post_split_min_value > MAX_MONEY) + { + emit minStakeSplitValueValid(ui->minPostSplitOutputValue, false); + } + else + { + emit minStakeSplitValueValid(ui->minPostSplitOutputValue, true); + } + } + } } return QDialog::eventFilter(object, event); } diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h index 4509795bdd..79a362830f 100644 --- a/src/qt/optionsdialog.h +++ b/src/qt/optionsdialog.h @@ -46,10 +46,15 @@ private slots: void updateStyle(); void hideStartMinimized(); void hideLimitTxnDisplayDate(); + void hideStakeSplitting(); void handleProxyIpValid(QValidatedLineEdit *object, bool fState); + void handleStakingEfficiencyValid(QValidatedLineEdit *object, bool fState); + void handleMinStakeSplitValueValid(QValidatedLineEdit *object, bool fState); signals: void proxyIpValid(QValidatedLineEdit *object, bool fValid); + void stakingEfficiencyValid(QValidatedLineEdit *object, bool fValid); + void minStakeSplitValueValid(QValidatedLineEdit *object, bool fValid); private: Ui::OptionsDialog *ui; @@ -58,6 +63,8 @@ private slots: bool fRestartWarningDisplayed_Proxy; bool fRestartWarningDisplayed_Lang; bool fProxyIpValid; + bool fStakingEfficiencyValid; + bool fMinStakeSplitValueValid; }; #endif // OPTIONSDIALOG_H diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index a8014f2db8..b5757081b2 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -1,5 +1,6 @@ #include "optionsmodel.h" #include "bitcoinunits.h" +#include "miner.h" #include #include @@ -142,6 +143,18 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const return QVariant(gArgs.GetBoolArg("-disableupdatecheck", false)); case DataDir: return settings.value("dataDir", QString::fromStdString(gArgs.GetArg("-datadir", GetDataDir().string()))); + case EnableStaking: + // This comes from the core and is a read-write setting (see below). + return QVariant(gArgs.GetBoolArg("-staking", true)); + case EnableStakeSplit: + // This comes from the core and is a read-write setting (see below). + return QVariant(gArgs.GetBoolArg("-enablestakesplit")); + case StakingEfficiency: + // This comes from the core and is a read-write setting (see below). + return QVariant((double) gArgs.GetArg("-stakingefficiency", (int64_t) 90)); + case MinStakeSplitValue: + // This comes from the core and is a read-write setting (see below). + return QVariant((qint64) gArgs.GetArg("-minstakesplitvalue", MIN_STAKE_SPLIT_VALUE_GRC)); default: return QVariant(); } @@ -275,6 +288,31 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in // be changed while the wallet is running. dataDir = value.toString(); settings.setValue("dataDir", dataDir); + break; + case EnableStaking: + // This is a core setting stored in the read-write settings file and once set will override the read-only + //config file. + gArgs.ForceSetArg("-staking", value.toBool() ? "1" : "0"); + updateRwSetting("staking", gArgs.GetBoolArg("-staking", true)); + break; + case EnableStakeSplit: + // This is a core setting stored in the read-write settings file and once set will override the read-only + //config file. + //fStakeSplitEnabled = value.toBool(); + gArgs.ForceSetArg("-enablestakesplit", value.toBool() ? "1" : "0"); + updateRwSetting("enablestakesplit", gArgs.GetBoolArg("-enablestakesplit")); + break; + case StakingEfficiency: + // This is a core setting stored in the read-write settings file and once set will override the read-only + //config file. + gArgs.ForceSetArg("-stakingefficiency", value.toString().toStdString()); + updateRwSetting("stakingefficiency", gArgs.GetArg("-stakingefficiency", 90)); + break; + case MinStakeSplitValue: + // This is a core setting stored in the read-write settings file and once set will override the read-only + //config file. + gArgs.ForceSetArg("-minstakesplitvalue", value.toString().toStdString()); + updateRwSetting("minstakesplitvalue", gArgs.GetArg("-minstakesplitvalue", MIN_STAKE_SPLIT_VALUE_GRC)); default: break; } diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 6d77b0a794..c940cb02fe 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -39,7 +39,11 @@ class OptionsModel : public QAbstractListModel LimitTxnDate, // QDate DisableUpdateCheck, // bool DataDir, // QString - OptionIDRowCount, + EnableStaking, // bool + EnableStakeSplit, // bool + StakingEfficiency, // double + MinStakeSplitValue, // int + OptionIDRowCount }; void Init(); diff --git a/src/util/system.h b/src/util/system.h index 7671c84649..66184086eb 100644 --- a/src/util/system.h +++ b/src/util/system.h @@ -108,6 +108,7 @@ class ArgsManager ALLOW_INT = 0x02, ALLOW_STRING = 0x04, ALLOW_ANY = ALLOW_BOOL | ALLOW_INT | ALLOW_STRING, + IMMEDIATE_EFFECT = 0x08, DEBUG_ONLY = 0x100, /* Some options would cause cross-contamination if values for * mainnet were used while running on regtest/testnet (or vice-versa). @@ -117,7 +118,7 @@ class ArgsManager NETWORK_ONLY = 0x200, // This argument's value is sensitive (such as a password). SENSITIVE = 0x400, - COMMAND = 0x800, + COMMAND = 0x800 }; protected: From 352716fbc4b0bc30478a42e43c91de8470db1f0f Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 6 Jun 2021 21:51:24 -0400 Subject: [PATCH 2/4] Implement listsettings This provides an rpc command to list all settings in rpc format. --- src/rpc/misc.cpp | 14 +++++++++ src/rpc/server.cpp | 1 + src/rpc/server.h | 1 + src/util/system.cpp | 75 +++++++++++++++++++++++++++++++++++++++++++++ src/util/system.h | 16 ++++++++-- 5 files changed, 104 insertions(+), 3 deletions(-) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 9e8164b0f6..36a92cf6b6 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -82,3 +82,17 @@ UniValue logging(const UniValue& params, bool fHelp) return result; } + +UniValue listsettings(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size()) + { + throw runtime_error( + "listsettings\n" + "Outputs all arguments/settings in JSON format.\n" + ); + } + + return gArgs.OutputArgs(); +} + diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 0a0b0f36b9..eedb940d2b 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -377,6 +377,7 @@ static const CRPCCommand vRPCCommands[] = { "listdata", &listdata, cat_developer }, { "listprojects", &listprojects, cat_developer }, { "listresearcheraccounts", &listresearcheraccounts, cat_developer }, + { "listsettings", &listsettings, cat_developer }, { "logging", &logging, cat_developer }, { "network", &network, cat_developer }, { "parseaccrualsnapshotfile",&parseaccrualsnapshotfile,cat_developer }, diff --git a/src/rpc/server.h b/src/rpc/server.h index 761b22f713..3969d8a010 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -191,6 +191,7 @@ extern UniValue inspectaccrualsnapshot(const UniValue& params, bool fHelp); extern UniValue listdata(const UniValue& params, bool fHelp); extern UniValue listprojects(const UniValue& params, bool fHelp); extern UniValue listresearcheraccounts(const UniValue& params, bool fHelp); +extern UniValue listsettings(const UniValue& params, bool fHelp); extern UniValue logging(const UniValue& params, bool fHelp); extern UniValue network(const UniValue& params, bool fHelp); extern UniValue parseaccrualsnapshotfile(const UniValue& params, bool fHelp); diff --git a/src/util/system.cpp b/src/util/system.cpp index b1d35eb171..e1eb46fc2f 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -1014,6 +1014,43 @@ void ArgsManager::logArgsPrefix( } } +UniValue ArgsManager::OutputArgsSection( + const std::string& section, + const std::map>& args) const +{ + UniValue result(UniValue::VOBJ); + UniValue settings(UniValue::VARR); + + std::string section_str = section.empty() ? "" : "[" + section + "] "; + for (const auto& arg : args) { + + UniValue setting(UniValue::VOBJ); + + for (const auto& value : arg.second) { + std::optional flags = GetArgFlags('-' + arg.first); + if (flags) { + if (*flags & SENSITIVE) + { + setting.pushKV(arg.first, "****"); + } + else + { + setting.pushKV(arg.first, value); + } + + setting.pushKV("changeable_without_restart", (*flags & IMMEDIATE_EFFECT) ? "true" : "false"); + + settings.push_back(setting); + } + } + } + + result.pushKV("section", section_str); + result.pushKV("settings", settings); + + return result; +} + void ArgsManager::LogArgs() const { LOCK(cs_args); @@ -1026,6 +1063,44 @@ void ArgsManager::LogArgs() const logArgsPrefix("Command-line arg:", "", m_settings.command_line_options); } +UniValue ArgsManager::OutputArgs() const +{ + UniValue result(UniValue::VOBJ); + UniValue sections(UniValue::VARR); + UniValue args_section(UniValue::VOBJ); + UniValue settings(UniValue::VARR); + + LOCK(cs_args); + + for (const auto& section : m_settings.ro_config) { + + args_section = OutputArgsSection(section.first, section.second); + sections.push_back(args_section); + } + result.pushKV("ro_config_file_args", sections); + + // There are no sections for rw_settings and the command line. + for (const auto& setting : m_settings.rw_settings) { + UniValue arg(UniValue::VOBJ); + std::optional flags = GetArgFlags('-' + setting.first); + + arg.pushKV(setting.first, setting.second); + + arg.pushKV("changeable_without_restart", (*flags & IMMEDIATE_EFFECT) ? "true" : "false"); + + settings.push_back(arg); + } + + result.pushKV("setting_file_args", settings); + + args_section.clear(); + args_section = OutputArgsSection("none", m_settings.command_line_options); + result.pushKV("command_line_args", find_value(args_section, "settings")); + + return result; +} + + // When we port the interfaces file over from Bitcoin, these two functions should be moved there. util::SettingsValue getRwSetting(const std::string& name) { diff --git a/src/util/system.h b/src/util/system.h index 66184086eb..213e1daa8c 100644 --- a/src/util/system.h +++ b/src/util/system.h @@ -378,12 +378,22 @@ class ArgsManager */ void LogArgs() const; + /** + * Output the settings as UniValue. + */ + UniValue OutputArgs() const; + private: // Helper function for LogArgs(). void logArgsPrefix( - const std::string& prefix, - const std::string& section, - const std::map>& args) const; + const std::string& prefix, + const std::string& section, + const std::map>& args) const; + + UniValue OutputArgsSection( + const std::string& section, + const std::map>& args) const; + }; extern ArgsManager gArgs; From 1988cfa1480c17b6df1dcc1b1e23877ffa44160a Mon Sep 17 00:00:00 2001 From: jamescowens Date: Mon, 7 Jun 2021 18:23:05 -0400 Subject: [PATCH 3/4] Implement changesettings --- src/rpc/misc.cpp | 137 ++++++++++++++++++++++++++++++++++++++++++++ src/rpc/server.cpp | 1 + src/rpc/server.h | 1 + src/util/system.cpp | 6 +- 4 files changed, 141 insertions(+), 4 deletions(-) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 36a92cf6b6..42097c5fde 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -96,3 +96,140 @@ UniValue listsettings(const UniValue& params, bool fHelp) return gArgs.OutputArgs(); } +UniValue changesettings(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() < 1) + { + throw runtime_error( + "changesettings [name=value] ... [name=value]\n" + "\n" + "name=value: name and value pair for setting to store/change (1st mandatory, 2nd+ optional).\n" + "\n" + "Note that the settings should be done in the same format as config file entries.\n" + "\n" + "Example:" + "changesettings enable enablestakesplit=1 stakingefficiency=98 minstakesplitvalue=800\n" + ); + } + + // -------- name ------------ value - value_changed - immediate_effect + std::map> valid_settings; + + UniValue result(UniValue::VOBJ); + UniValue settings_stored_with_no_state_change(UniValue::VARR); + UniValue settings_immediate(UniValue::VARR); + UniValue settings_applied_requiring_restart(UniValue::VARR); + //UniValue invalid_settings_ignored(UniValue::VARR); + + // Validation + for (unsigned int i = 0; i < params.size(); ++i) + { + std::string param = params[i].get_str(); + + if (param.size() > 0 && param[0] == '-') + { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Incorrectly formatted setting change: " + param); + } + + std::string::size_type pos; + std::string name; + std::string value; + + if ((pos = param.find('=')) != std::string::npos) + { + name = param.substr(0, pos); + value = param.substr(pos + 1); + } + else + { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Incorrectly formatted setting change: " + param); + } + + std::optional flags = gArgs.GetArgFlags('-' + name); + + if (!flags) + { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid setting: " + param); + } + + // TODO: Record explicit default state for settings. + // This currently has a problem that I am not sure yet how to solve. Settings that are defaulted to true, unless + // they are set to the contrary, such as -staking, will falsely indicate a change because the defaulted state is + // not explicitly stored for comparison. After there is an explicit entry defined in the settings file, it works + // correctly. + + // Also, the overloading of GetArg is NOT helpful here... + std::string current_value; + + // It is either a string or a number.... One of these will succeed. + try + { + current_value = gArgs.GetArg(name, "never_used_default"); + } + catch (std::exception& e) + { + // If it is a number convert back to a string. + current_value = ToString(gArgs.GetArg(name, 1)); + } + + bool value_changed = (current_value != value); + bool immediate_effect = *flags & ArgsManager::IMMEDIATE_EFFECT; + + auto insert_pair = valid_settings.insert(std::make_pair( + name, std::make_tuple(value, value_changed, immediate_effect))); + + if (!insert_pair.second) + { + throw JSONRPCError(RPC_INVALID_PARAMETER, "changesettings does not support more than one instance of the same " + "setting: " + param); + } + } + + // Now that validation is done do the update work. + bool restart_required = false; + + for (const auto& setting : valid_settings) + { + const std::string& name = setting.first; + const std::string& value = std::get<0>(setting.second); + const bool& value_changed = std::get<1>(setting.second); + const bool& immediate_effect = std::get<2>(setting.second); + + std::string param = name + "=" + value; + + // Regardless, store in r-w settings file. + if (!updateRwSetting(name, value)) + { + throw JSONRPCError(RPC_MISC_ERROR, "Error storing setting in read-write settings file."); + } + + if (value_changed) + { + gArgs.ForceSetArg(name, value); + + if (immediate_effect) + { + settings_immediate.push_back(param); + } + else + { + settings_applied_requiring_restart.push_back(param); + + // Record if restart required. + restart_required |= !immediate_effect; + } + } + else + { + settings_stored_with_no_state_change.push_back(param); + } + } + + result.pushKV("settings_change_requires_restart", restart_required); + result.pushKV("settings_stored_with_no_state_change", settings_stored_with_no_state_change); + result.pushKV("settings_changed_taking_immediate_effect", settings_immediate); + result.pushKV("settings_changed_requiring_restart", settings_applied_requiring_restart); + + return result; +} + diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index eedb940d2b..85a5701454 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -366,6 +366,7 @@ static const CRPCCommand vRPCCommands[] = { "auditsnapshotaccrual", &auditsnapshotaccrual, cat_developer }, { "auditsnapshotaccruals", &auditsnapshotaccruals, cat_developer }, { "addkey", &addkey, cat_developer }, + { "changesettings", &changesettings, cat_developer }, { "currentcontractaverage", ¤tcontractaverage, cat_developer }, { "debug", &debug, cat_developer }, { "dumpcontracts", &dumpcontracts, cat_developer }, diff --git a/src/rpc/server.h b/src/rpc/server.h index 3969d8a010..df48464023 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -221,6 +221,7 @@ extern UniValue scraperreport(const UniValue& params, bool fHelp); // Network extern UniValue addnode(const UniValue& params, bool fHelp); extern UniValue askforoutstandingblocks(const UniValue& params, bool fHelp); +extern UniValue changesettings(const UniValue& params, bool fHelp); extern UniValue clearbanned(const UniValue& params, bool fHelp); extern UniValue currenttime(const UniValue& params, bool fHelp); extern UniValue getaddednodeinfo(const UniValue& params, bool fHelp); diff --git a/src/util/system.cpp b/src/util/system.cpp index e1eb46fc2f..24494c12ad 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -1038,7 +1038,7 @@ UniValue ArgsManager::OutputArgsSection( setting.pushKV(arg.first, value); } - setting.pushKV("changeable_without_restart", (*flags & IMMEDIATE_EFFECT) ? "true" : "false"); + setting.pushKV("changeable_without_restart", (bool)(*flags & IMMEDIATE_EFFECT)); settings.push_back(setting); } @@ -1086,7 +1086,7 @@ UniValue ArgsManager::OutputArgs() const arg.pushKV(setting.first, setting.second); - arg.pushKV("changeable_without_restart", (*flags & IMMEDIATE_EFFECT) ? "true" : "false"); + arg.pushKV("changeable_without_restart", (bool)(*flags & IMMEDIATE_EFFECT)); settings.push_back(arg); } @@ -1263,5 +1263,3 @@ std::pair WinCmdLineArgs::get() } #endif } // namespace util - - From 14a5646e5018dce876795b5cd07f24402456cb6f Mon Sep 17 00:00:00 2001 From: jamescowens Date: Wed, 9 Jun 2021 09:57:07 -0400 Subject: [PATCH 4/4] Implement dynamic sidestaking entries This commit introduces two new settings for sidestaking, -sidestakeaddresses=address1,address2,..., addressN -sidestakeallocations=alloc1,alloc2,...,allocN These may be used in both the config file and with changesettings as an alternative to the original sidestake=address,allocation entries. If the new entries are present, are not empty, and are correctly filled out then they will take precedence over the older entries. The reason this is necessary is that the read-write settings file does not support multiple instances of the same setting, so a restructure was required to support the r-w override. --- src/gridcoin/staking/status.cpp | 2 +- src/gridcoin/staking/status.h | 2 +- src/init.cpp | 17 +++- src/miner.cpp | 171 ++++++++++++++++++-------------- src/miner.h | 2 +- src/qt/bitcoingui.cpp | 2 +- src/rpc/mining.cpp | 5 +- src/rpc/misc.cpp | 3 +- 8 files changed, 121 insertions(+), 83 deletions(-) diff --git a/src/gridcoin/staking/status.cpp b/src/gridcoin/staking/status.cpp index 5f1f718545..d2d834f9c0 100644 --- a/src/gridcoin/staking/status.cpp +++ b/src/gridcoin/staking/status.cpp @@ -18,7 +18,7 @@ namespace { //! constexpr const char* STAKING_ERROR_STRINGS[] { "None", - "Commanded disabled", + "Disabled by configuration", "No Mature Coins", "No coins", "Entire balance reserved", diff --git a/src/gridcoin/staking/status.h b/src/gridcoin/staking/status.h index 1c2728d1c6..e921e53304 100644 --- a/src/gridcoin/staking/status.h +++ b/src/gridcoin/staking/status.h @@ -20,7 +20,7 @@ class MinerStatus enum ReasonNotStakingCategory { NONE, - COMMANDED_DISABLED, + DISABLED_BY_CONFIGURATION, NO_MATURE_COINS, NO_COINS, ENTIRE_BALANCE_RESERVED, diff --git a/src/init.cpp b/src/init.cpp index 7c3e53aea6..c1b19a128b 100755 --- a/src/init.cpp +++ b/src/init.cpp @@ -363,8 +363,21 @@ void SetupServerArgs() argsman.AddArg("-sidestake=", "Sidestake destination and allocation entry. There can be as many " "specified as desired. Only six per stake can be sent. If more than " "six are specified. Six are randomly chosen for each stake. Only active " - "if -enablesidestaking is set.", - ArgsManager::ALLOW_ANY, OptionsCategory::STAKING); + "if -enablesidestaking is set. These settings are overridden if " + "-sidestakeaddresses and -stakestakeallocations are set.", + ArgsManager::ALLOW_ANY | ArgsManager::IMMEDIATE_EFFECT, OptionsCategory::STAKING); + argsman.AddArg("-sidestakeaddresses=", "Sidestake destination entry. There can be as many " + "specified as desired. Only six per stake can be sent. If more than " + "six are specified. Six are randomly chosen for each stake. Only active " + "if -enablesidestaking is set. If set along with -sidestakeallocations " + "overrides the -sidestake entries.", + ArgsManager::ALLOW_ANY | ArgsManager::IMMEDIATE_EFFECT, OptionsCategory::STAKING); + argsman.AddArg("-sidestakeallocations=percent1,percent2,...,percentN>", "Sidestake allocation entry. There can be as many " + "specified as desired. Only six per stake can be sent. If more than " + "six are specified. Six are randomly chosen for each stake. Only active " + "if -enablesidestaking is set. If set along with -sidestakeaddresses " + "overrides the -sidestake entries.", + ArgsManager::ALLOW_ANY | ArgsManager::IMMEDIATE_EFFECT, OptionsCategory::STAKING); argsman.AddArg("-enablestakesplit", "Enable unspent output spitting when staking to optimize staking efficiency " "(default: 0", ArgsManager::ALLOW_ANY | ArgsManager::IMMEDIATE_EFFECT, OptionsCategory::STAKING); diff --git a/src/miner.cpp b/src/miner.cpp index 443b914397..19b9019e0d 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1180,7 +1180,7 @@ bool IsMiningAllowed(CWallet *pwallet) if (!gArgs.GetBoolArg("-staking", true)) { LOCK(g_miner_status.lock); - g_miner_status.SetReasonNotStaking(GRC::MinerStatus::COMMANDED_DISABLED); + g_miner_status.SetReasonNotStaking(GRC::MinerStatus::DISABLED_BY_CONFIGURATION); status = false; } @@ -1189,87 +1189,108 @@ bool IsMiningAllowed(CWallet *pwallet) // This function parses the config file for the directives for side staking. It is used // in StakeMiner for the miner loop and also called by rpc getmininginfo. -bool GetSideStakingStatusAndAlloc(SideStakeAlloc& vSideStakeAlloc) +SideStakeAlloc GetSideStakingStatusAndAlloc() { - vector vSubParam; - std::string sAddress; - double dAllocation = 0.0; + SideStakeAlloc vSideStakeAlloc; + std::vector> raw_vSideStakeAlloc; double dSumAllocation = 0.0; - bool fEnableSideStaking = gArgs.GetBoolArg("-enablesidestaking"); - LogPrint(BCLog::LogFlags::MINER, "StakeMiner: fEnableSideStaking = %u", fEnableSideStaking); + // Parse destinations and allocations. We don't need to worry about any that are rejected other than a warning + // message, because any unallocated rewards will go back into the coinstake output(s). - // If side staking is enabled, parse destinations and allocations. We don't need to worry about any that are rejected - // other than a warning message, because any unallocated rewards will go back into the coinstake output(s). - if (fEnableSideStaking) + // If -sidestakeaddresses and -sidestakeallocations is set in either the config file or the r-w settings file + // and the settings are not empty and they are the same size, this will take precedence over the multiple entry + // -sidestake format. + std::vector addresses; + std::vector allocations; + + ParseString(gArgs.GetArg("-sidestakeaddresses", ""), ',', addresses); + ParseString(gArgs.GetArg("-sidestakeallocations", ""), ',', allocations); + + if (addresses.size() != allocations.size()) + { + LogPrintf("WARN: %s: Malformed new style sidestaking configuration entries. Reverting to original format.", + __func__); + } + + if (addresses.size() && addresses.size() == allocations.size()) + { + for (unsigned int i = 0; i < addresses.size(); ++i) + { + raw_vSideStakeAlloc.push_back(std::make_pair(addresses[i], allocations[i])); + } + } + else if (gArgs.GetArgs("-sidestake").size()) { - if (gArgs.GetArgs("-sidestake").size()) + for (auto const& sSubParam : gArgs.GetArgs("-sidestake")) { - for (auto const& sSubParam : gArgs.GetArgs("-sidestake")) + std::vector vSubParam; + + ParseString(sSubParam, ',', vSubParam); + if (vSubParam.size() != 2) { - ParseString(sSubParam, ',', vSubParam); - if (vSubParam.size() != 2) - { - LogPrintf("WARN: StakeMiner: Incompletely SideStake Allocation specified. Skipping SideStake entry."); - vSubParam.clear(); - continue; - } + LogPrintf("WARN: %s: Incomplete SideStake Allocation specified. Skipping SideStake entry.", __func__); + continue; + } - sAddress = vSubParam[0]; + raw_vSideStakeAlloc.push_back(std::make_pair(vSubParam[0], vSubParam[1])); + } + } - CBitcoinAddress address(sAddress); - if (!address.IsValid()) - { - LogPrintf("WARN: StakeMiner: ignoring sidestake invalid address %s.", sAddress.c_str()); - vSubParam.clear(); - continue; - } + for (auto const& entry : raw_vSideStakeAlloc) + { + std::string sAddress; + double dAllocation = 0.0; - try - { - dAllocation = stof(vSubParam[1]) / 100.0; - } - catch(...) - { - LogPrintf("WARN: StakeMiner: Invalid allocation provided. Skipping allocation."); - vSubParam.clear(); - continue; - } + sAddress = entry.first; - if (dAllocation <= 0) - { - LogPrintf("WARN: StakeMiner: Negative or zero allocation provided. Skipping allocation."); - vSubParam.clear(); - continue; - } + CBitcoinAddress address(sAddress); + if (!address.IsValid()) + { + LogPrintf("WARN: %s: ignoring sidestake invalid address %s.", __func__, sAddress); + continue; + } - // The below will stop allocations if someone has made a mistake and the total adds up to more than 100%. - // Note this same check is also done in SplitCoinStakeOutput, but it needs to be done here for two reasons: - // 1. Early alertment in the debug log, rather than when the first kernel is found, and 2. When the UI is - // hooked up, the SideStakeAlloc vector will be filled in by other than reading the config file and will - // skip the above code. - dSumAllocation += dAllocation; - if (dSumAllocation > 1.0) - { - LogPrintf("WARN: StakeMiner: allocation percentage over 100\%, ending sidestake allocations."); - break; - } + try + { + dAllocation = stof(entry.second) / 100.0; + } + catch (...) + { + LogPrintf("WARN: %s: Invalid allocation provided. Skipping allocation.", __func__); + continue; + } - vSideStakeAlloc.push_back(std::pair(sAddress, dAllocation)); - LogPrint(BCLog::LogFlags::MINER, "StakeMiner: SideStakeAlloc Address %s, Allocation %f", - sAddress.c_str(), dAllocation); + if (dAllocation <= 0) + { + LogPrintf("WARN: %s: Negative or zero allocation provided. Skipping allocation.", __func__); + continue; + } - vSubParam.clear(); - } + // The below will stop allocations if someone has made a mistake and the total adds up to more than 100%. + // Note this same check is also done in SplitCoinStakeOutput, but it needs to be done here for two reasons: + // 1. Early alertment in the debug log, rather than when the first kernel is found, and 2. When the UI is + // hooked up, the SideStakeAlloc vector will be filled in by other than reading the config file and will + // skip the above code. + dSumAllocation += dAllocation; + if (dSumAllocation > 1.0) + { + LogPrintf("WARN: %s: allocation percentage over 100\%, ending sidestake allocations.", __func__); + break; } - // If we get here and dSumAllocation is zero then the enablesidestaking flag was set, but no VALID distribution - // was provided in the config file, so warn in the debug log. - if (!dSumAllocation) - LogPrintf("WARN: StakeMiner: enablesidestaking was set in config but nothing has been allocated for" - " distribution!"); + + vSideStakeAlloc.push_back(std::pair(sAddress, dAllocation)); + LogPrint(BCLog::LogFlags::MINER, "INFO: %s: SideStakeAlloc Address %s, Allocation %f", + __func__, sAddress, dAllocation); } - return fEnableSideStaking; + // If we get here and dSumAllocation is zero then the enablesidestaking flag was set, but no VALID distribution + // was provided in the config file, so warn in the debug log. + if (!dSumAllocation) + LogPrintf("WARN: %s: enablesidestaking was set in config but nothing has been allocated for" + " distribution!"); + + return vSideStakeAlloc; } // This function parses the config file for the directives for stake splitting. It is used @@ -1325,17 +1346,21 @@ void StakeMiner(CWallet *pwallet) int64_t nMinStakeSplitValue = 0; double dEfficiency = 0; int64_t nDesiredStakeOutputValue = 0; - SideStakeAlloc vSideStakeAlloc = {}; - - // nMinStakeSplitValue and dEfficiency are out parameters. - bool fEnableStakeSplit = GetStakeSplitStatusAndParams(nMinStakeSplitValue, dEfficiency, nDesiredStakeOutputValue); - - // vSideStakeAlloc is an out parameter. - bool fEnableSideStaking = GetSideStakingStatusAndAlloc(vSideStakeAlloc); + SideStakeAlloc vSideStakeAlloc; while (!fShutdown) { - //wait for next round + // nMinStakeSplitValue and dEfficiency are out parameters. + bool fEnableStakeSplit = GetStakeSplitStatusAndParams(nMinStakeSplitValue, dEfficiency, nDesiredStakeOutputValue); + + bool fEnableSideStaking = gArgs.GetBoolArg("-enablesidestaking"); + + LogPrint(BCLog::LogFlags::MINER, "StakeMiner: fEnableSideStaking = %u", fEnableSideStaking); + + // vSideStakeAlloc is an out parameter. + if (fEnableSideStaking) vSideStakeAlloc = GetSideStakingStatusAndAlloc(); + + // wait for next round MilliSleep(nMinerSleep); g_timer.InitTimer("miner", LogInstance().WillLogCategory(BCLog::LogFlags::MISC)); diff --git a/src/miner.h b/src/miner.h index 343920bea5..e3b238382f 100644 --- a/src/miner.h +++ b/src/miner.h @@ -25,7 +25,7 @@ std::optional GetLastStake(CWallet& wallet); void SplitCoinStakeOutput(CBlock &blocknew, int64_t &nReward, bool &fEnableStakeSplit, bool &fEnableSideStaking, SideStakeAlloc &vSideStakeAlloc, double &dEfficiency); unsigned int GetNumberOfStakeOutputs(int64_t &nValue, int64_t &nMinStakeSplitValue, double &dEfficiency); -bool GetSideStakingStatusAndAlloc(SideStakeAlloc& vSideStakeAlloc); +SideStakeAlloc GetSideStakingStatusAndAlloc(); bool GetStakeSplitStatusAndParams(int64_t& nMinStakeSplitValue, double& dEfficiency, int64_t& nDesiredStakeOutputValue); #endif // NOVACOIN_MINER_H diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index fabbf9f362..f47653d3ff 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -705,7 +705,7 @@ void BitcoinGUI::createToolBars() } else { - labelStakingIcon->setToolTip(tr("Not staking: Commanded disabled.")); + labelStakingIcon->setToolTip(tr("Not staking: Disabled by configuration.")); } statusBar()->addPermanentWidget(frameBlocks); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 5deb0e517b..b29285e315 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -111,8 +111,9 @@ UniValue getmininginfo(const UniValue& params, bool fHelp) // nMinStakeSplitValue, dEfficiency, and nDesiredStakeSplitValue are out parameters. bool fEnableStakeSplit = GetStakeSplitStatusAndParams(nMinStakeSplitValue, dEfficiency, nDesiredStakeSplitValue); - // vSideStakeAlloc is an out parameter. - bool fEnableSideStaking = GetSideStakingStatusAndAlloc(vSideStakeAlloc); + bool fEnableSideStaking = gArgs.GetBoolArg("-enablesidestaking"); + + vSideStakeAlloc = GetSideStakingStatusAndAlloc(); stakesplitting.pushKV("stake-splitting-enabled", fEnableStakeSplit); if (fEnableStakeSplit) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 42097c5fde..4519e3cbc2 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -166,7 +166,7 @@ UniValue changesettings(const UniValue& params, bool fHelp) { current_value = gArgs.GetArg(name, "never_used_default"); } - catch (std::exception& e) + catch (...) { // If it is a number convert back to a string. current_value = ToString(gArgs.GetArg(name, 1)); @@ -232,4 +232,3 @@ UniValue changesettings(const UniValue& params, bool fHelp) return result; } -