diff --git a/src/qt/pivx/settings/forms/settingswalletoptionswidget.ui b/src/qt/pivx/settings/forms/settingswalletoptionswidget.ui index 1bbea14e9..4df7a8f89 100644 --- a/src/qt/pivx/settings/forms/settingswalletoptionswidget.ui +++ b/src/qt/pivx/settings/forms/settingswalletoptionswidget.ui @@ -167,10 +167,10 @@ - 8 + 0 - 0 + 1 999999 diff --git a/src/qt/pivx/settings/settingswalletoptionswidget.cpp b/src/qt/pivx/settings/settingswalletoptionswidget.cpp index 284745db7..f802ad77e 100644 --- a/src/qt/pivx/settings/settingswalletoptionswidget.cpp +++ b/src/qt/pivx/settings/settingswalletoptionswidget.cpp @@ -100,20 +100,27 @@ void SettingsWalletOptionsWidget::setSpinBoxStakeSplitThreshold(double val) void SettingsWalletOptionsWidget::onSpinBoxStakeSplitThresholdChanged() { - if (ui->spinBoxStakeSplitThreshold->value() > 0) { - if (ui->spinBoxAutoCombineThreshold->value() >= ui->spinBoxStakeSplitThreshold->value() * 2) { - ui->spinBoxAutoCombineThreshold->setValue(ui->spinBoxStakeSplitThreshold->value() * 2 - 1); + if (ui->spinBoxStakeSplitThreshold->value() > 1) { + if (ui->spinBoxAutoCombineThreshold->value() >= ui->spinBoxStakeSplitThreshold->value() * 2 - 1) { + ui->spinBoxAutoCombineThreshold->setValue(floor(ui->spinBoxStakeSplitThreshold->value() * 2 - 1)); } + } else { + ui->spinBoxAutoCombineThreshold->setValue(1); } } void SettingsWalletOptionsWidget::onSpinBoxAutoCombineThresholdChanged() { - if (ui->spinBoxStakeSplitThreshold->value() > 0) { - if (ui->spinBoxAutoCombineThreshold->value() >= ui->spinBoxStakeSplitThreshold->value() * 2) { - ui->spinBoxAutoCombineThreshold->setValue(ui->spinBoxStakeSplitThreshold->value() * 2 - 1); + if (ui->spinBoxStakeSplitThreshold->value() > 1) { + if (ui->spinBoxAutoCombineThreshold->value() >= ui->spinBoxStakeSplitThreshold->value() * 2 - 1) { + ui->spinBoxAutoCombineThreshold->setValue(floor(ui->spinBoxStakeSplitThreshold->value() * 2 - 1)); } + } else { + ui->spinBoxAutoCombineThreshold->setValue(1); } + + // Enforce only integers. + ui->spinBoxAutoCombineThreshold->setValue(floor(ui->spinBoxAutoCombineThreshold->value())); } void SettingsWalletOptionsWidget::onAutoCombineCheckboxStateChanged() diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 637a99caf..0d5fee3b9 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2969,7 +2969,7 @@ UniValue setautocombinethreshold(const JSONRPCRequest& request) "}\n" "\nExamples:\n" + - HelpExampleCli("setautocombinethreshold", "true 500.12") + HelpExampleRpc("setautocombinethreshold", "true, 500.12")); + HelpExampleCli("setautocombinethreshold", "true 500") + HelpExampleRpc("setautocombinethreshold", "true, 500")); RPCTypeCheck(request.params, {UniValue::VBOOL, UniValue::VNUM}); @@ -2983,6 +2983,8 @@ UniValue setautocombinethreshold(const JSONRPCRequest& request) nThreshold = AmountFromValue(request.params[1]); if (nThreshold < COIN) throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("The threshold value cannot be less than %s", FormatMoney(COIN))); + if (nThreshold % COIN != 0) + throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("The threshold value must be an integer")); } CWalletDB walletdb(pwalletMain->strWalletFile); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f875b8c4c..ba2cc479d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1652,9 +1652,9 @@ CAmount CWallet::GetStakingBalance() const { return std::max(CAmount(0), loopTxsBalance( [](const uint256& id, const CWalletTx& pcoin, CAmount& nTotal) { - if (pcoin.IsTrusted() && - pcoin.GetDepthInMainChain() - >= + if (pcoin.IsTrusted() && + pcoin.GetDepthInMainChain() + >= (Params().GetConsensus().NetworkUpgradeActive(chainActive.Height(), Consensus::UPGRADE_STAKE_MIN_DEPTH_V2) ? Params().GetConsensus().nStakeMinDepthV2 : Params().GetConsensus().nStakeMinDepth) ) { @@ -1811,7 +1811,7 @@ bool CWallet::GetMasternodeVinAndKeys(CTxIn& txinRet, CPubKey& pubKeyRet, CKey& CTxOut txOut = wtx.vout[nOutputIndex]; // Masternode collateral value - if (!CMasternode::CheckMasternodeCollateral(txOut.nValue)) + if (!CMasternode::CheckMasternodeCollateral(txOut.nValue)) { strError = "Invalid collateral tx value"; return error("%s: tx %s, index %d not a masternode collateral", __func__, strTxHash, nOutputIndex); @@ -1864,7 +1864,7 @@ bool CWallet::AvailableCoins(std::vector* pCoins, // --> populates { if (pCoins) pCoins->clear(); const bool fCoinsSelected = (coinControl != nullptr) && coinControl->HasSelected(); - + { LOCK2(cs_main, cs_wallet); for (std::map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { @@ -1877,9 +1877,9 @@ bool CWallet::AvailableCoins(std::vector* pCoins, // --> populates continue; // Check min depth requirement for stake inputs - if (nCoinType == STAKEABLE_COINS && - nDepth - < + if (nCoinType == STAKEABLE_COINS && + nDepth + < (Params().GetConsensus().NetworkUpgradeActive(chainActive.Height(), Consensus::UPGRADE_STAKE_MIN_DEPTH_V2) ? Params().GetConsensus().nStakeMinDepthV2 : Params().GetConsensus().nStakeMinDepth)) continue; @@ -2504,7 +2504,7 @@ bool CWallet::CreateCoinStake( if (WITH_LOCK(cs_main, return chainActive.Height()) != pindexPrev->nHeight) return false; // Make sure the wallet is unlocked and shutdown hasn't been requested - if (IsLocked() || ShutdownRequested()) return false; + if (IsLocked() || ShutdownRequested()) return false; nCredit = 0; @@ -2624,7 +2624,7 @@ CWallet::CommitResult CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& AddToWallet(wtxNew); // Notify that old coins are spent - + std::set updated_hashes; for (const CTxIn& txin : wtxNew.vin) { // notify only once @@ -3243,12 +3243,17 @@ void CWallet::AutoCombineDust(CConnman* connman) return; } - std::map > mapCoinsByAddress = AvailableCoinsByAddress(true, nAutoCombineThreshold * COIN); + // Make sure we don't break the settings saved in the old wallets where the autocombine threshold was saved incorrectly. + CAmount adjustedAutoCombineThreshold = nAutoCombineThreshold; + if (nAutoCombineThreshold < COIN) { + adjustedAutoCombineThreshold = nAutoCombineThreshold * COIN; + } + + std::map > mapCoinsByAddress = AvailableCoinsByAddress(true, adjustedAutoCombineThreshold); //coins are sectioned by address. This combination code only wants to combine inputs that belong to the same address for (std::map >::iterator it = mapCoinsByAddress.begin(); it != mapCoinsByAddress.end(); it++) { std::vector vCoins, vRewardCoins; - bool maxSize = false; vCoins = it->second; // We don't want the tx to be refused for being too large @@ -3271,13 +3276,12 @@ void CWallet::AutoCombineDust(CConnman* connman) nTotalRewardsValue += out.Value(); // Combine to the threshold and not way above - if (nTotalRewardsValue > nAutoCombineThreshold * COIN) + if (nTotalRewardsValue > adjustedAutoCombineThreshold) break; // Around 180 bytes per input. We use 190 to be certain txSizeEstimate += 190; if (txSizeEstimate >= MAX_STANDARD_TX_SIZE - 200) { - maxSize = true; break; } } @@ -3318,7 +3322,7 @@ void CWallet::AutoCombineDust(CConnman* connman) } //we don't combine below the threshold unless the fees are 0 to avoid paying fees over fees over fees - if (!maxSize && nTotalRewardsValue < nAutoCombineThreshold * COIN && nFeeRet > 0) + if (nTotalRewardsValue < adjustedAutoCombineThreshold && nFeeRet > 0) continue; const CWallet::CommitResult& res = CommitTransaction(wtx, keyChange, connman);