From 17045fe506592257ebf4e155b787a49979cacac4 Mon Sep 17 00:00:00 2001 From: jamescowens Date: Sun, 30 Aug 2020 17:52:04 -0400 Subject: [PATCH] Fix for self-transactions in listtransactions --- src/wallet/wallet.cpp | 44 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 9ba8aceaa1..30d9ed146e 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -778,8 +778,16 @@ void CWalletTx::GetAmounts(list& listReceived, list& strSentAccount = strFromAccount; + // This is the same as nDebit > 0, i.e. we sent the transaction. bool fIsFromMe = IsFromMe(); + // This will be true if this is a self-transaction. + bool fIsAllToMe = true; + for (auto const& txout : vout) + { + fIsAllToMe = fIsAllToMe && (pwallet->IsMine(txout) != ISMINE_NO); + } + // Used for coinstake rollup. int64_t amount = 0; @@ -790,11 +798,11 @@ void CWalletTx::GetAmounts(list& listReceived, list& // Compute fee: int64_t nDebit = GetDebit(filter); - // debit > 0 means we signed/sent this transaction, we do not record a fee for + // fIsFromMe true means we signed/sent this transaction, we do not record a fee for // coinstakes. The fees collected from other transactions in the block are added // to the staker's output(s) that are the staker's. Therefore fees only need // to be shown for non-coinstake send transactions. - if (nDebit > 0 && !fIsCoinStake) + if (fIsFromMe && !fIsCoinStake) { int64_t nValueOut = GetValueOut(); nFee = nDebit - nValueOut; @@ -808,7 +816,7 @@ void CWalletTx::GetAmounts(list& listReceived, list& // Only need to handle txouts if AT LEAST one of these is true: // 1) they debit from us (sent) // 2) the output is to us (received) - if (nDebit > 0) + if (fIsFromMe) { // If not a coinstake, don't report 'change' txouts. Txouts on change addresses for coinstakes // must be reported because a change address itself can stake, and there is no "change" on a @@ -830,7 +838,7 @@ void CWalletTx::GetAmounts(list& listReceived, list& // We exclude coinstake outputs 0 and 1 from sends, because output 0 is empty and output 1 MUST go back to // the staker (i.e. is not a send by definition). Notice that for a normal self-transaction, the send and // receive details will be suppressed; however, the fee will be reported in the nFee parameter. - if (fIsMine == ISMINE_NO && ((i > 1 && fIsCoinStakeMine) || (!fIsCoinStake && nDebit > 0))) + if (fIsMine == ISMINE_NO && ((i > 1 && fIsCoinStakeMine) || (!fIsCoinStake && fIsFromMe))) { if (!ExtractDestination(txout.scriptPubKey, address)) { @@ -888,6 +896,34 @@ void CWalletTx::GetAmounts(list& listReceived, list& output = {address, txout.nValue, (int) i}; listReceived.push_back(output); } + + // Self-transactions... + + if (fIsFromMe && fIsAllToMe) + { + if (!ExtractDestination(txout.scriptPubKey, address)) + { + if (txout.scriptPubKey[0] != OP_RETURN) + { + LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s", + this->GetHash().ToString().c_str()); + } + + address = CNoDestination(); + } + + // For a self-transaction, the output has to be both a send and a receive. Note that an + // unfortunate side-effect of this solution for self-transaction listing is that the fee + // will be reported on both the send and receive transactions in the ListTransactions that + // normally calls this function, but that is better than simply reporting the receive side only + // of a self-transaction, which is typically what is done. + // + // Also, a mixed transaction where some of the outputs are back to oneself, and others are to + // other addressees, does not qualify here. Those only the output sends will be reported. + output = {address, txout.nValue, (int) i}; + listSent.push_back(output); + listReceived.push_back(output); + } } }