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..b5f23419ca 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -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 (std::exception& e)
+ {
+ 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/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)