mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 20:42:59 +01:00
Add COutput::fSafe member for safe handling of unconfirmed outputs
This exposes a value computed in CWallet::AvailableCoins so it can used for other things, like inclusion in listunspent output.
This commit is contained in:
parent
8910b4717e
commit
af61d9f78b
@ -20,7 +20,7 @@ static void addCoin(const CAmount& nValue, const CWallet& wallet, std::vector<CO
|
|||||||
CWalletTx* wtx = new CWalletTx(&wallet, MakeTransactionRef(std::move(tx)));
|
CWalletTx* wtx = new CWalletTx(&wallet, MakeTransactionRef(std::move(tx)));
|
||||||
|
|
||||||
int nAge = 6 * 24;
|
int nAge = 6 * 24;
|
||||||
COutput output(wtx, nInput, nAge, true, true);
|
COutput output(wtx, nInput, nAge, true /* spendable */, true /* solvable */, true /* safe */);
|
||||||
vCoins.push_back(output);
|
vCoins.push_back(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,7 +580,7 @@ void WalletModel::getOutputs(const std::vector<COutPoint>& vOutpoints, std::vect
|
|||||||
if (!wallet->mapWallet.count(outpoint.hash)) continue;
|
if (!wallet->mapWallet.count(outpoint.hash)) continue;
|
||||||
int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain();
|
int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain();
|
||||||
if (nDepth < 0) continue;
|
if (nDepth < 0) continue;
|
||||||
COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true, true);
|
COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true /* spendable */, true /* solvable */, true /* safe */);
|
||||||
vOutputs.push_back(out);
|
vOutputs.push_back(out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -607,7 +607,7 @@ void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins)
|
|||||||
if (!wallet->mapWallet.count(outpoint.hash)) continue;
|
if (!wallet->mapWallet.count(outpoint.hash)) continue;
|
||||||
int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain();
|
int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain();
|
||||||
if (nDepth < 0) continue;
|
if (nDepth < 0) continue;
|
||||||
COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true, true);
|
COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true /* spendable */, true /* solvable */, true /* safe */);
|
||||||
if (outpoint.n < out.tx->tx->vout.size() && wallet->IsMine(out.tx->tx->vout[outpoint.n]) == ISMINE_SPENDABLE)
|
if (outpoint.n < out.tx->tx->vout.size() && wallet->IsMine(out.tx->tx->vout[outpoint.n]) == ISMINE_SPENDABLE)
|
||||||
vCoins.push_back(out);
|
vCoins.push_back(out);
|
||||||
}
|
}
|
||||||
@ -619,7 +619,7 @@ void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins)
|
|||||||
while (wallet->IsChange(cout.tx->tx->vout[cout.i]) && cout.tx->tx->vin.size() > 0 && wallet->IsMine(cout.tx->tx->vin[0]))
|
while (wallet->IsChange(cout.tx->tx->vout[cout.i]) && cout.tx->tx->vin.size() > 0 && wallet->IsMine(cout.tx->tx->vin[0]))
|
||||||
{
|
{
|
||||||
if (!wallet->mapWallet.count(cout.tx->tx->vin[0].prevout.hash)) break;
|
if (!wallet->mapWallet.count(cout.tx->tx->vin[0].prevout.hash)) break;
|
||||||
cout = COutput(&wallet->mapWallet[cout.tx->tx->vin[0].prevout.hash], cout.tx->tx->vin[0].prevout.n, 0, true, true);
|
cout = COutput(&wallet->mapWallet[cout.tx->tx->vin[0].prevout.hash], cout.tx->tx->vin[0].prevout.n, 0 /* depth */, true /* spendable */, true /* solvable */, true /* safe */);
|
||||||
}
|
}
|
||||||
|
|
||||||
CTxDestination address;
|
CTxDestination address;
|
||||||
|
@ -54,7 +54,7 @@ static void add_coin(const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = fa
|
|||||||
wtx->fDebitCached = true;
|
wtx->fDebitCached = true;
|
||||||
wtx->nDebitCached = 1;
|
wtx->nDebitCached = 1;
|
||||||
}
|
}
|
||||||
COutput output(wtx.get(), nInput, nAge, true, true);
|
COutput output(wtx.get(), nInput, nAge, true /* spendable */, true /* solvable */, true /* safe */);
|
||||||
vCoins.push_back(output);
|
vCoins.push_back(output);
|
||||||
wtxn.emplace_back(std::move(wtx));
|
wtxn.emplace_back(std::move(wtx));
|
||||||
}
|
}
|
||||||
|
@ -1946,7 +1946,7 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const
|
|||||||
return nTotal;
|
return nTotal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWallet::AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl, bool fIncludeZeroValue) const
|
void CWallet::AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe, const CCoinControl *coinControl, bool fIncludeZeroValue) const
|
||||||
{
|
{
|
||||||
vCoins.clear();
|
vCoins.clear();
|
||||||
|
|
||||||
@ -1960,9 +1960,6 @@ void CWallet::AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed,
|
|||||||
if (!CheckFinalTx(*pcoin))
|
if (!CheckFinalTx(*pcoin))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (fOnlyConfirmed && !pcoin->IsTrusted())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
|
if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1975,6 +1972,8 @@ void CWallet::AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed,
|
|||||||
if (nDepth == 0 && !pcoin->InMempool())
|
if (nDepth == 0 && !pcoin->InMempool())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
bool safeTx = pcoin->IsTrusted();
|
||||||
|
|
||||||
// We should not consider coins from transactions that are replacing
|
// We should not consider coins from transactions that are replacing
|
||||||
// other transactions.
|
// other transactions.
|
||||||
//
|
//
|
||||||
@ -1990,8 +1989,8 @@ void CWallet::AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed,
|
|||||||
// be a 1-block reorg away from the chain where transactions A and C
|
// be a 1-block reorg away from the chain where transactions A and C
|
||||||
// were accepted to another chain where B, B', and C were all
|
// were accepted to another chain where B, B', and C were all
|
||||||
// accepted.
|
// accepted.
|
||||||
if (nDepth == 0 && fOnlyConfirmed && pcoin->mapValue.count("replaces_txid")) {
|
if (nDepth == 0 && pcoin->mapValue.count("replaces_txid")) {
|
||||||
continue;
|
safeTx = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Similarly, we should not consider coins from transactions that
|
// Similarly, we should not consider coins from transactions that
|
||||||
@ -2002,7 +2001,11 @@ void CWallet::AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed,
|
|||||||
// intending to replace A', but potentially resulting in a scenario
|
// intending to replace A', but potentially resulting in a scenario
|
||||||
// where A, A', and D could all be accepted (instead of just B and
|
// where A, A', and D could all be accepted (instead of just B and
|
||||||
// D, or just A and A' like the user would want).
|
// D, or just A and A' like the user would want).
|
||||||
if (nDepth == 0 && fOnlyConfirmed && pcoin->mapValue.count("replaced_by_txid")) {
|
if (nDepth == 0 && pcoin->mapValue.count("replaced_by_txid")) {
|
||||||
|
safeTx = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fOnlySafe && !safeTx) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2014,7 +2017,7 @@ void CWallet::AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed,
|
|||||||
vCoins.push_back(COutput(pcoin, i, nDepth,
|
vCoins.push_back(COutput(pcoin, i, nDepth,
|
||||||
((mine & ISMINE_SPENDABLE) != ISMINE_NO) ||
|
((mine & ISMINE_SPENDABLE) != ISMINE_NO) ||
|
||||||
(coinControl && coinControl->fAllowWatchOnly && (mine & ISMINE_WATCH_SOLVABLE) != ISMINE_NO),
|
(coinControl && coinControl->fAllowWatchOnly && (mine & ISMINE_WATCH_SOLVABLE) != ISMINE_NO),
|
||||||
(mine & (ISMINE_SPENDABLE | ISMINE_WATCH_SOLVABLE)) != ISMINE_NO));
|
(mine & (ISMINE_SPENDABLE | ISMINE_WATCH_SOLVABLE)) != ISMINE_NO, safeTx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -466,12 +466,23 @@ public:
|
|||||||
const CWalletTx *tx;
|
const CWalletTx *tx;
|
||||||
int i;
|
int i;
|
||||||
int nDepth;
|
int nDepth;
|
||||||
|
|
||||||
|
/** Whether we have the private keys to spend this output */
|
||||||
bool fSpendable;
|
bool fSpendable;
|
||||||
|
|
||||||
|
/** Whether we know how to spend this output, ignoring the lack of keys */
|
||||||
bool fSolvable;
|
bool fSolvable;
|
||||||
|
|
||||||
COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn, bool fSolvableIn)
|
/**
|
||||||
|
* Whether this output is considered safe to spend. Unconfirmed transactions
|
||||||
|
* from outside keys and unconfirmed replacement transactions are considered
|
||||||
|
* unsafe and will not be used to fund new spending transactions.
|
||||||
|
*/
|
||||||
|
bool fSafe;
|
||||||
|
|
||||||
|
COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn, bool fSolvableIn, bool fSafeIn)
|
||||||
{
|
{
|
||||||
tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn; fSolvable = fSolvableIn;
|
tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn; fSolvable = fSolvableIn; fSafe = fSafeIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
@ -740,7 +751,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* populate vCoins with vector of available COutputs.
|
* populate vCoins with vector of available COutputs.
|
||||||
*/
|
*/
|
||||||
void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL, bool fIncludeZeroValue=false) const;
|
void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = NULL, bool fIncludeZeroValue=false) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shuffle and select coins until nTargetValue is reached while avoiding
|
* Shuffle and select coins until nTargetValue is reached while avoiding
|
||||||
|
Loading…
Reference in New Issue
Block a user