diff --git a/src/coincontrol.h b/src/coincontrol.h index 4a72a4fa8aef..08907caadd85 100644 --- a/src/coincontrol.h +++ b/src/coincontrol.h @@ -28,6 +28,13 @@ class CCoinControl bool fOverrideFeeRate; //! Feerate to use if overrideFeeRate is true CFeeRate nFeeRate; + //! Flag to decide whether delegations utxo are included in the calculation or not. + bool fIncludeDelegated{true}; + //! Flag to decide whether cold staking utxo are included in the calculation or not + //! (always false in spending process for obvious reasons). + bool fIncludeColdStaking{false}; + //! Whether should only select trusted coins. + bool fOnlyTrusted{true}; CCoinControl() { @@ -46,6 +53,9 @@ class CCoinControl fOverrideFeeRate = false; fSplitBlock = false; nSplitBlock = 1; + fIncludeDelegated = true; + fIncludeColdStaking = false; + fOnlyTrusted = true; } bool HasSelected() const diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 147b1270681a..f3dd49326965 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -7,6 +7,7 @@ #include "walletmodel.h" #include "addresstablemodel.h" +#include "coincontrol.h" #include "guiconstants.h" #include "optionsmodel.h" #include "recentrequeststablemodel.h" @@ -99,7 +100,12 @@ CAmount WalletModel::getBalance(const CCoinControl* coinControl, bool fIncludeDe if (coinControl) { CAmount nBalance = 0; std::vector vCoins; - wallet->AvailableCoins(&vCoins, coinControl, fIncludeDelegated); + + // Refactor me.. + CCoinControl _coinControl = *coinControl; + _coinControl.fIncludeDelegated = fIncludeDelegated; + + wallet->AvailableCoins(&vCoins, &_coinControl); for (const COutput& out : vCoins) { bool fSkip = fUnlockedOnly && isLockedCoin(out.tx->GetHash(), out.i); if (out.fSpendable && !fSkip) @@ -412,7 +418,6 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact coinControl, recipients[0].inputType, true, - recipients[0].useSwiftTX, 0, fIncludeDelegations); transaction.setTransactionFee(nFeeRequired); @@ -851,7 +856,9 @@ void WalletModel::getOutputs(const std::vector& vOutpoints, std::vect bool WalletModel::getMNCollateralCandidate(COutPoint& outPoint) { std::vector vCoins; - wallet->AvailableCoins(&vCoins, nullptr, false, false, ONLY_10000); + CCoinControl coinControl; + coinControl.fIncludeDelegated = false; + wallet->AvailableCoins(&vCoins, &coinControl, ONLY_10000); for (const COutput& out : vCoins) { // skip locked collaterals if (!isLockedCoin(out.tx->GetHash(), out.i)) { diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 31ad2469b940..ec1ee334e28a 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -1,9 +1,10 @@ // Copyright (c) 2009-2012 The Bitcoin developers // Copyright (c) 2015-2020 The PIVX developers // Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php. #include "activemasternode.h" +#include "coincontrol.h" #include "db.h" #include "init.h" #include "main.h" @@ -401,7 +402,9 @@ UniValue getmasternodeoutputs (const JSONRPCRequest& request) // Find possible candidates std::vector possibleCoins; - pwalletMain->AvailableCoins(&possibleCoins, nullptr, false, false, ONLY_10000); + CCoinControl coinControl; + coinControl.fIncludeDelegated = false; + pwalletMain->AvailableCoins(&possibleCoins, &coinControl, ONLY_10000); UniValue ret(UniValue::VARR); for (COutput& out : possibleCoins) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index f0505388f4ed..be52ba7c4668 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1097,7 +1097,7 @@ UniValue CreateColdStakeDelegation(const UniValue& params, CWalletTx& wtxNew, CR // Create the transaction CAmount nFeeRequired; - if (!pwalletMain->CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError, nullptr, ALL_COINS, /*fUseIX*/ false, (CAmount)0, fUseDelegated)) { + if (!pwalletMain->CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError, nullptr, ALL_COINS, (CAmount)0, fUseDelegated)) { if (nValue + nFeeRequired > currBalance) strError = strprintf("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!", FormatMoney(nFeeRequired)); LogPrintf("%s : %s\n", __func__, strError); @@ -3194,6 +3194,7 @@ UniValue listunspent(const JSONRPCRequest& request) CCoinControl coinControl; coinControl.fAllowWatchOnly = nWatchonlyConfig == 2; + coinControl.fOnlyTrusted = false; UniValue results(UniValue::VARR); std::vector vecOutputs; @@ -3201,12 +3202,8 @@ UniValue listunspent(const JSONRPCRequest& request) LOCK2(cs_main, pwalletMain->cs_wallet); pwalletMain->AvailableCoins(&vecOutputs, &coinControl, // coin control - true, // include delegated - false, // include cold staking - ALL_COINS, // coin type - false, // only confirmed - false // use IX - ); + ALL_COINS); // coin type + for (const COutput& out : vecOutputs) { if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth) continue; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a5c304f60558..b6c20fe36ffe 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1910,15 +1910,13 @@ void CWallet::GetAvailableP2CSCoins(std::vector& vCoins) const { /** * Test if the transaction is spendable. */ -bool CheckTXAvailability(const CWalletTx* pcoin, bool fOnlyConfirmed, bool fUseIX, int& nDepth) +bool CheckTXAvailability(const CWalletTx* pcoin, bool fOnlyConfirmed, int& nDepth) { if (!CheckFinalTx(*pcoin)) return false; if (fOnlyConfirmed && !pcoin->IsTrusted()) return false; if (pcoin->GetBlocksToMaturity() > 0) return false; nDepth = pcoin->GetDepthInMainChain(false); - // do not use IX for inputs that have less then 6 blockchain confirmations - if (fUseIX && nDepth < 6) return false; // We should not consider coins which aren't at least in our mempool // It's possible for these to be conflicted via ancestors which we may never be able to detect @@ -1971,7 +1969,7 @@ bool CWallet::GetMasternodeVinAndKeys(CTxIn& txinRet, CPubKey& pubKeyRet, CKey& // Check availability int nDepth = 0; - if (!CheckTXAvailability(&wtx, true, false, nDepth)) { + if (!CheckTXAvailability(&wtx, true, nDepth)) { strError = "Not available collateral transaction"; return error("%s: tx %s not available", __func__, strTxHash); } @@ -2006,19 +2004,17 @@ bool CWallet::GetMasternodeVinAndKeys(CTxIn& txinRet, CPubKey& pubKeyRet, CKey& */ bool CWallet::AvailableCoins(std::vector* pCoins, // --> populates when != nullptr const CCoinControl* coinControl, // Default: nullptr - bool fIncludeDelegated, // Default: true - bool fIncludeColdStaking, // Default: false - AvailableCoinsType nCoinType, // Default: ALL_COINS - bool fOnlyConfirmed, // Default: true - bool fUseIX // Default: false + AvailableCoinsType nCoinType // Default: ALL_COINS ) const { if (pCoins) pCoins->clear(); const bool fCoinsSelected = (coinControl != nullptr) && coinControl->HasSelected(); // include delegated coins when coinControl is active - if (!fIncludeDelegated && fCoinsSelected) + bool fIncludeDelegated = true; + if (coinControl && !coinControl->fIncludeDelegated && fCoinsSelected) fIncludeDelegated = true; + bool fOnlyTrusted = (coinControl && coinControl->fOnlyTrusted) || !coinControl; { LOCK2(cs_main, cs_wallet); for (std::map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { @@ -2027,7 +2023,7 @@ bool CWallet::AvailableCoins(std::vector* pCoins, // --> populates // Check if the tx is selectable int nDepth; - if (!CheckTXAvailability(pcoin, fOnlyConfirmed, fUseIX, nDepth)) + if (!CheckTXAvailability(pcoin, fOnlyTrusted, nDepth)) continue; // Check min depth requirement for stake inputs @@ -2063,7 +2059,7 @@ bool CWallet::AvailableCoins(std::vector* pCoins, // --> populates // --Skip P2CS outputs // skip cold coins - if (mine == ISMINE_COLD && (!fIncludeColdStaking || !HasDelegator(pcoin->vout[i]))) continue; + if (mine == ISMINE_COLD && ((coinControl && !coinControl->fIncludeColdStaking) || !HasDelegator(pcoin->vout[i]))) continue; // skip delegated coins if (mine == ISMINE_SPENDABLE_DELEGATED && !fIncludeDelegated) continue; @@ -2071,7 +2067,7 @@ bool CWallet::AvailableCoins(std::vector* pCoins, // --> populates bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable)) || - ((mine & ((fIncludeColdStaking ? ISMINE_COLD : ISMINE_NO) | + ((mine & (coinControl && (coinControl->fIncludeColdStaking ? ISMINE_COLD : ISMINE_NO) | (fIncludeDelegated ? ISMINE_SPENDABLE_DELEGATED : ISMINE_NO) )) != ISMINE_NO); // found valid coin @@ -2087,12 +2083,12 @@ std::map > CWallet::AvailableCoinsByAddres { std::vector vCoins; // include cold + CCoinControl coinControl; + coinControl.fIncludeColdStaking = true; + coinControl.fOnlyTrusted = fConfirmed; AvailableCoins(&vCoins, - nullptr, // coin control - true, // fIncludeDelegated - true, // fIncludeColdStaking - ALL_COINS, // coin type - fConfirmed); // only confirmed + &coinControl, // coin control + ALL_COINS); // coin type std::map > mapCoins; for (COutput& out : vCoins) { @@ -2160,10 +2156,11 @@ bool CWallet::StakeableCoins(std::vector* pCoins) const bool fIncludeCold = (sporkManager.IsSporkActive(SPORK_17_COLDSTAKING_ENFORCEMENT) && GetBoolArg("-coldstaking", DEFAULT_COLDSTAKING)); + CCoinControl coinControl; + coinControl.fIncludeDelegated = false; + coinControl.fIncludeColdStaking = fIncludeCold; return AvailableCoins(pCoins, - nullptr, // coin control - false, // fIncludeDelegated - fIncludeCold, // fIncludeColdStaking + &coinControl, // coin control STAKEABLE_COINS); // coin type } @@ -2385,12 +2382,9 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, const CCoinControl* coinControl, AvailableCoinsType coin_type, bool sign, - bool useIX, CAmount nFeePay, bool fIncludeDelegated) { - if (useIX && nFeePay < CENT) nFeePay = CENT; - CAmount nValue = 0; int nChangePosRequest = nChangePosInOut; @@ -2415,13 +2409,17 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, LOCK2(cs_main, cs_wallet); { std::vector vAvailableCoins; + + // Refactor me.. + CCoinControl _coinControl; + if (coinControl) { + _coinControl = *coinControl; + } + _coinControl.fIncludeDelegated = fIncludeDelegated; + _coinControl.fOnlyTrusted = true; AvailableCoins(&vAvailableCoins, - coinControl, - fIncludeDelegated, - false, // fIncludeColdStaking - coin_type, - true, // fOnlyConfirmed - useIX); + &_coinControl, + coin_type); nFeeRet = 0; if (nFeePay > 0) nFeeRet = nFeePay; @@ -2473,10 +2471,6 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, strFailReason = _("Insufficient funds."); } - if (useIX) { - strFailReason += " " + _("SwiftX requires inputs with at least 6 confirmations, you might need to wait a few minutes and try again."); - } - return false; } @@ -2658,12 +2652,12 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, return true; } -bool CWallet::CreateTransaction(CScript scriptPubKey, const CAmount& nValue, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl, AvailableCoinsType coin_type, bool useIX, CAmount nFeePay, bool fIncludeDelegated) +bool CWallet::CreateTransaction(CScript scriptPubKey, const CAmount& nValue, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl, AvailableCoinsType coin_type, CAmount nFeePay, bool fIncludeDelegated) { std::vector vecSend; vecSend.emplace_back(scriptPubKey, nValue, false); int nChangePosInOut = -1; - return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, nChangePosInOut, strFailReason, coinControl, coin_type, true, useIX, nFeePay, fIncludeDelegated); + return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, nChangePosInOut, strFailReason, coinControl, coin_type, true, nFeePay, fIncludeDelegated); } bool CWallet::CreateCoinStake( diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index ce8e177f0a42..56ffaebdf834 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -386,12 +386,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface //! >> Available coins (generic) bool AvailableCoins(std::vector* pCoins, // --> populates when != nullptr const CCoinControl* coinControl = nullptr, - bool fIncludeDelegated = true, - bool fIncludeColdStaking = false, - AvailableCoinsType nCoinType = ALL_COINS, - bool fOnlyConfirmed = true, - bool fUseIX = false - ) const; + AvailableCoinsType nCoinType = ALL_COINS) const; //! >> Available coins (spending) bool SelectCoinsToSpend(const std::vector& vAvailableCoins, const CAmount& nTargetValue, std::set >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl = nullptr) const; bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, std::vector vCoins, std::set >& setCoinsRet, CAmount& nValueRet) const; @@ -550,10 +545,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface const CCoinControl* coinControl = NULL, AvailableCoinsType coin_type = ALL_COINS, bool sign = true, - bool useIX = false, CAmount nFeePay = 0, bool fIncludeDelegated = false); - bool CreateTransaction(CScript scriptPubKey, const CAmount& nValue, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl = NULL, AvailableCoinsType coin_type = ALL_COINS, bool useIX = false, CAmount nFeePay = 0, bool fIncludeDelegated = false); + bool CreateTransaction(CScript scriptPubKey, const CAmount& nValue, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl = NULL, AvailableCoinsType coin_type = ALL_COINS, CAmount nFeePay = 0, bool fIncludeDelegated = false); // enumeration for CommitResult (return status of CommitTransaction) enum CommitStatus