Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/coincontrol.h
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand All @@ -46,6 +53,9 @@ class CCoinControl
fOverrideFeeRate = false;
fSplitBlock = false;
nSplitBlock = 1;
fIncludeDelegated = true;
fIncludeColdStaking = false;
fOnlyTrusted = true;
}

bool HasSelected() const
Expand Down
13 changes: 10 additions & 3 deletions src/qt/walletmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "walletmodel.h"

#include "addresstablemodel.h"
#include "coincontrol.h"
#include "guiconstants.h"
#include "optionsmodel.h"
#include "recentrequeststablemodel.h"
Expand Down Expand Up @@ -99,7 +100,12 @@ CAmount WalletModel::getBalance(const CCoinControl* coinControl, bool fIncludeDe
if (coinControl) {
CAmount nBalance = 0;
std::vector<COutput> 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)
Expand Down Expand Up @@ -412,7 +418,6 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
coinControl,
recipients[0].inputType,
true,
recipients[0].useSwiftTX,
0,
fIncludeDelegations);
transaction.setTransactionFee(nFeeRequired);
Expand Down Expand Up @@ -851,7 +856,9 @@ void WalletModel::getOutputs(const std::vector<COutPoint>& vOutpoints, std::vect
bool WalletModel::getMNCollateralCandidate(COutPoint& outPoint)
{
std::vector<COutput> 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)) {
Expand Down
7 changes: 5 additions & 2 deletions src/rpc/masternode.cpp
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -401,7 +402,9 @@ UniValue getmasternodeoutputs (const JSONRPCRequest& request)

// Find possible candidates
std::vector<COutput> 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) {
Expand Down
11 changes: 4 additions & 7 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -3194,19 +3194,16 @@ UniValue listunspent(const JSONRPCRequest& request)

CCoinControl coinControl;
coinControl.fAllowWatchOnly = nWatchonlyConfig == 2;
coinControl.fOnlyTrusted = false;

UniValue results(UniValue::VARR);
std::vector<COutput> vecOutputs;
assert(pwalletMain != NULL);
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;
Expand Down
66 changes: 30 additions & 36 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1910,15 +1910,13 @@ void CWallet::GetAvailableP2CSCoins(std::vector<COutput>& 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
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -2006,19 +2004,17 @@ bool CWallet::GetMasternodeVinAndKeys(CTxIn& txinRet, CPubKey& pubKeyRet, CKey&
*/
bool CWallet::AvailableCoins(std::vector<COutput>* 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;
Comment thread
furszy marked this conversation as resolved.

bool fOnlyTrusted = (coinControl && coinControl->fOnlyTrusted) || !coinControl;
{
LOCK2(cs_main, cs_wallet);
for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) {
Expand All @@ -2027,7 +2023,7 @@ bool CWallet::AvailableCoins(std::vector<COutput>* 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
Expand Down Expand Up @@ -2063,15 +2059,15 @@ bool CWallet::AvailableCoins(std::vector<COutput>* 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;
Comment thread
furszy marked this conversation as resolved.
// skip delegated coins
if (mine == ISMINE_SPENDABLE_DELEGATED && !fIncludeDelegated) continue;

bool solvable = IsSolvable(*this, pcoin->vout[i].scriptPubKey);

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) |
Comment thread
furszy marked this conversation as resolved.
(fIncludeDelegated ? ISMINE_SPENDABLE_DELEGATED : ISMINE_NO) )) != ISMINE_NO);

// found valid coin
Expand All @@ -2087,12 +2083,12 @@ std::map<CTxDestination , std::vector<COutput> > CWallet::AvailableCoinsByAddres
{
std::vector<COutput> 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<CTxDestination, std::vector<COutput> > mapCoins;
for (COutput& out : vCoins) {
Expand Down Expand Up @@ -2160,10 +2156,11 @@ bool CWallet::StakeableCoins(std::vector<COutput>* 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
}

Expand Down Expand Up @@ -2385,12 +2382,9 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& 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;

Expand All @@ -2415,13 +2409,17 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend,
LOCK2(cs_main, cs_wallet);
{
std::vector<COutput> 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;
Expand Down Expand Up @@ -2473,10 +2471,6 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& 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;
}

Expand Down Expand Up @@ -2658,12 +2652,12 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& 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<CRecipient> 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(
Expand Down
10 changes: 2 additions & 8 deletions src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -386,12 +386,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
//! >> Available coins (generic)
bool AvailableCoins(std::vector<COutput>* 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<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*, unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl = nullptr) const;
bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*, unsigned int> >& setCoinsRet, CAmount& nValueRet) const;
Expand Down Expand Up @@ -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
Expand Down