From 29641e3770164a074096b67e3b6f40c2164dc370 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Sat, 12 Oct 2019 00:49:47 +0200 Subject: [PATCH] [Wallet] Fix inconsistencies with GetDepthInMainChain --- src/qt/transactiondesc.cpp | 30 +++++++++++++----------------- src/qt/transactionrecord.cpp | 12 +++++++----- src/qt/walletmodel.cpp | 10 ++++++---- src/wallet/rpcwallet.cpp | 24 ++++++++++++++++-------- src/wallet/wallet.cpp | 19 ++++++++++++------- src/wallet/wallet.h | 2 ++ 6 files changed, 56 insertions(+), 41 deletions(-) diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 506f63d1a5e8..f6c229fef6c6 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -33,14 +33,19 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) else return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime)); } else { - int signatures = wtx.GetTransactionLockSignatures(); + const int signatures = wtx.GetTransactionLockSignatures(); QString strUsingIX = ""; + bool fConflicted; + const int nDepth = wtx.GetDepthAndMempool(fConflicted); + + if (nDepth < 0 || fConflicted) + return tr("conflicted"); + + const bool isOffline = (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0); + if (signatures >= 0) { if (signatures >= SWIFTTX_SIGNATURES_REQUIRED) { - int nDepth = wtx.GetDepthInMainChain(); - if (nDepth < 0) - return tr("conflicted"); - else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) + if (isOffline) return tr("%1/offline (verified via SwiftX)").arg(nDepth); else if (nDepth < 6) return tr("%1/confirmed (verified via SwiftX)").arg(nDepth); @@ -48,20 +53,14 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) return tr("%1 confirmations (verified via SwiftX)").arg(nDepth); } else { if (!wtx.IsTransactionLockTimedOut()) { - int nDepth = wtx.GetDepthInMainChain(); - if (nDepth < 0) - return tr("conflicted"); - else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) + if (isOffline) return tr("%1/offline (SwiftX verification in progress - %2 of %3 signatures)").arg(nDepth).arg(signatures).arg(SWIFTTX_SIGNATURES_TOTAL); else if (nDepth < 6) return tr("%1/confirmed (SwiftX verification in progress - %2 of %3 signatures )").arg(nDepth).arg(signatures).arg(SWIFTTX_SIGNATURES_TOTAL); else return tr("%1 confirmations (SwiftX verification in progress - %2 of %3 signatures)").arg(nDepth).arg(signatures).arg(SWIFTTX_SIGNATURES_TOTAL); } else { - int nDepth = wtx.GetDepthInMainChain(); - if (nDepth < 0) - return tr("conflicted"); - else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) + if (isOffline) return tr("%1/offline (SwiftX verification failed)").arg(nDepth); else if (nDepth < 6) return tr("%1/confirmed (SwiftX verification failed)").arg(nDepth); @@ -70,10 +69,7 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) } } } else { - int nDepth = wtx.GetDepthInMainChain(); - if (nDepth < 0) - return tr("conflicted"); - else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) + if (isOffline) return tr("%1/offline").arg(nDepth); else if (nDepth < 6) return tr("%1/unconfirmed").arg(nDepth); diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index e248407451dd..650f97c152d3 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -348,7 +348,9 @@ void TransactionRecord::updateStatus(const CWalletTx& wtx) wtx.nTimeReceived, idx); //status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0); - status.depth = wtx.GetDepthInMainChain(); + bool fConflicted; + status.depth = wtx.GetDepthAndMempool(fConflicted); + const bool isOffline = (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0); //Determine the depth of the block int nBlocksToMaturity = wtx.GetBlocksToMaturity(); @@ -374,7 +376,7 @@ void TransactionRecord::updateStatus(const CWalletTx& wtx) if (pindex && chainActive.Contains(pindex)) { // Check if the block was requested by anyone - if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) + if (isOffline) status.status = TransactionStatus::MaturesWarning; } else { status.status = TransactionStatus::NotAccepted; @@ -384,9 +386,9 @@ void TransactionRecord::updateStatus(const CWalletTx& wtx) status.matures_in = 0; } } else { - if (status.depth < 0) { + if (status.depth < 0 || fConflicted) { status.status = TransactionStatus::Conflicted; - } else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) { + } else if (isOffline) { status.status = TransactionStatus::Offline; } else if (status.depth == 0) { status.status = TransactionStatus::Unconfirmed; @@ -438,4 +440,4 @@ std::string TransactionRecord::statusToString(){ default: return "No status"; } -} \ No newline at end of file +} diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 2da7727a87cb..5f3b18cee0f2 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -863,8 +863,9 @@ void WalletModel::getOutputs(const std::vector& vOutpoints, std::vect LOCK2(cs_main, wallet->cs_wallet); for (const COutPoint& outpoint : vOutpoints) { if (!wallet->mapWallet.count(outpoint.hash)) continue; - int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain(); - if (nDepth < 0) continue; + bool fConflicted; + const int nDepth = wallet->mapWallet[outpoint.hash].GetDepthAndMempool(fConflicted); + if (nDepth < 0 || fConflicted) continue; COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true); vOutputs.push_back(out); } @@ -889,8 +890,9 @@ void WalletModel::listCoins(std::map >& mapCoins) // add locked coins for (const COutPoint& outpoint : vLockedCoins) { if (!wallet->mapWallet.count(outpoint.hash)) continue; - int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain(); - if (nDepth < 0) continue; + bool fConflicted; + int nDepth = wallet->mapWallet[outpoint.hash].GetDepthAndMempool(fConflicted); + if (nDepth < 0 || fConflicted) continue; COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true); if (outpoint.n < out.tx->vout.size() && wallet->IsMine(out.tx->vout[outpoint.n]) == ISMINE_SPENDABLE) vCoins.push_back(out); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 9a3159740740..f9a7929fd111 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -667,13 +667,16 @@ CAmount GetAccountBalance(CWalletDB& walletdb, const std::string& strAccount, in // Tally wallet transactions for (std::map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; - if (!IsFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0) + bool fConflicted; + int depth = wtx.GetDepthAndMempool(fConflicted); + + if (!IsFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || depth < 0 || fConflicted) continue; CAmount nReceived, nSent, nFee; wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter); - if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth) + if (nReceived != 0 && depth >= nMinDepth) nBalance += nReceived; nBalance -= nSent + nFee; } @@ -741,7 +744,10 @@ UniValue getbalance(const UniValue& params, bool fHelp) CAmount nBalance = 0; for (std::map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; - if (!IsFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0) + bool fConflicted; + int depth = wtx.GetDepthAndMempool(fConflicted); + + if (!IsFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || depth < 0 || fConflicted) continue; CAmount allFee; @@ -749,7 +755,7 @@ UniValue getbalance(const UniValue& params, bool fHelp) std::list listReceived; std::list listSent; wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter); - if (wtx.GetDepthInMainChain() >= nMinDepth) { + if (depth >= nMinDepth) { for (const COutputEntry& r : listReceived) nBalance += r.amount; } @@ -1276,7 +1282,8 @@ void ListTransactions(const CWalletTx& wtx, const std::string& strAccount, int n } // Received - if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth) { + int depth = wtx.GetDepthInMainChain(); + if (listReceived.size() > 0 && depth >= nMinDepth) { for (const COutputEntry& r : listReceived) { std::string account; if (pwalletMain->mapAddressBook.count(r.destination)) @@ -1288,7 +1295,7 @@ void ListTransactions(const CWalletTx& wtx, const std::string& strAccount, int n entry.push_back(Pair("account", account)); MaybePushAddress(entry, r.destination); if (wtx.IsCoinBase()) { - if (wtx.GetDepthInMainChain() < 1) + if (depth < 1) entry.push_back(Pair("category", "orphan")); else if (wtx.GetBlocksToMaturity() > 0) entry.push_back(Pair("category", "immature")); @@ -1497,8 +1504,9 @@ UniValue listaccounts(const UniValue& params, bool fHelp) std::string strSentAccount; std::list listReceived; std::list listSent; - int nDepth = wtx.GetDepthInMainChain(); - if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0) + bool fConflicted; + int nDepth = wtx.GetDepthAndMempool(fConflicted); + if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0 || fConflicted) continue; wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly); mapAccountBalances[strSentAccount] -= nFee; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5604a2d834c4..c0f525e71167 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1553,7 +1553,7 @@ bool CWalletTx::InMempool() const void CWalletTx::RelayWalletTransaction(std::string strCommand) { LOCK(cs_main); - if (!IsCoinBase()) { + if (!IsCoinBase() && !IsCoinStake()) { if (GetDepthInMainChain() == 0 && !isAbandoned()) { uint256 hash = GetHash(); LogPrintf("Relaying wtx %s\n", hash.ToString()); @@ -1851,11 +1851,6 @@ void CWallet::AvailableCoins( if (nDepth == 0 && !pcoin->InMempool()) continue; - // 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 - if (nDepth == 0 && !pcoin->InMempool()) - continue; - for (unsigned int i = 0; i < pcoin->vout.size(); i++) { bool found = false; if (nCoinType == ONLY_DENOMINATED) { @@ -3031,7 +3026,10 @@ std::map CWallet::GetAddressBalances() if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0) continue; - int nDepth = pcoin->GetDepthInMainChain(); + bool fConflicted; + int nDepth = pcoin->GetDepthAndMempool(fConflicted); + if (fConflicted) + continue; if (nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1)) continue; @@ -5562,6 +5560,13 @@ bool CWalletTx::IsTrusted() const return true; } +int CWalletTx::GetDepthAndMempool(bool& fConflicted, bool enableIX) const +{ + int ret = GetDepthInMainChain(enableIX); + fConflicted = (ret == 0 && !InMempool()); // not in chain nor in mempool + return ret; +} + void CWalletTx::MarkDirty() { fCreditCached = false; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index c785ff52f96b..94c42ff4586e 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -786,6 +786,8 @@ class CWalletTx : public CMerkleTx void BindWallet(CWallet* pwalletIn); + int GetDepthAndMempool(bool& fConflicted, bool enableIX = true) const; + //! filter decides which addresses will count towards the debit CAmount GetDebit(const isminefilter& filter) const; CAmount GetCredit(const isminefilter& filter) const;