From f3fbe99fcf90daec79d49fd5d868102dc99feb23 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sat, 15 Dec 2018 19:52:03 +0000 Subject: [PATCH] GUI: TransactionRecord: Refactor to turn send-to-self into send+receive pairs --- src/interfaces/wallet.h | 1 + src/qt/transactionrecord.cpp | 138 +++++++++++++++-------------------- src/wallet/interfaces.cpp | 1 + 3 files changed, 59 insertions(+), 81 deletions(-) diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h index f26ac866dcf..b5d98e36fe6 100644 --- a/src/interfaces/wallet.h +++ b/src/interfaces/wallet.h @@ -387,6 +387,7 @@ struct WalletTx CTransactionRef tx; std::vector txin_is_mine; std::vector txout_is_mine; + std::vector txout_is_change; std::vector txout_address; std::vector txout_address_is_mine; CAmount credit; diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 4b48b124d47..8a373451eb6 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -54,16 +54,63 @@ QList TransactionRecord::decomposeTransaction(const interface } } - if (!any_from_me) { - // - // Credit - // + if (fAllFromMe || !any_from_me) { + for (const isminetype mine : wtx.txout_is_mine) + { + if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true; + } + + CAmount nTxFee = nDebit - wtx.tx->GetValueOut(); + for(unsigned int i = 0; i < wtx.tx->vout.size(); i++) { const CTxOut& txout = wtx.tx->vout[i]; + + if (wtx.txout_is_change[i]) { + continue; + } + + if (fAllFromMe) { + // + // Debit + // + + TransactionRecord sub(hash, nTime); + sub.idx = i; + sub.involvesWatchAddress = involvesWatchAddress; + + if (!std::get_if(&wtx.txout_address[i])) + { + // Sent to Bitcoin Address + sub.type = TransactionRecord::SendToAddress; + sub.address = EncodeDestination(wtx.txout_address[i]); + } + else + { + // Sent to IP, or other non-address transaction like OP_EVAL + sub.type = TransactionRecord::SendToOther; + sub.address = mapValue["to"]; + } + + CAmount nValue = txout.nValue; + /* Add fee to first output */ + if (nTxFee > 0) + { + nValue += nTxFee; + nTxFee = 0; + } + sub.debit = -nValue; + + parts.append(sub); + } + isminetype mine = wtx.txout_is_mine[i]; if(mine) { + // + // Credit + // + TransactionRecord sub(hash, nTime); sub.idx = i; // vout index sub.credit = txout.nValue; @@ -89,83 +136,12 @@ QList TransactionRecord::decomposeTransaction(const interface parts.append(sub); } } - } - else - { - isminetype fAllToMe = ISMINE_SPENDABLE; - for (const isminetype mine : wtx.txout_is_mine) - { - if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true; - if(fAllToMe > mine) fAllToMe = mine; - } - - if (fAllFromMe && fAllToMe) - { - // Payment to self - std::string address; - for (auto it = wtx.txout_address.begin(); it != wtx.txout_address.end(); ++it) { - if (it != wtx.txout_address.begin()) address += ", "; - address += EncodeDestination(*it); - } - - CAmount nChange = wtx.change; - parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, address, -(nDebit - nChange), nCredit - nChange)); - parts.last().involvesWatchAddress = involvesWatchAddress; // maybe pass to TransactionRecord as constructor argument - } - else if (fAllFromMe) - { - // - // Debit - // - CAmount nTxFee = nDebit - wtx.tx->GetValueOut(); - - for (unsigned int nOut = 0; nOut < wtx.tx->vout.size(); nOut++) - { - const CTxOut& txout = wtx.tx->vout[nOut]; - TransactionRecord sub(hash, nTime); - sub.idx = nOut; - sub.involvesWatchAddress = involvesWatchAddress; - - if(wtx.txout_is_mine[nOut]) - { - // Ignore parts sent to self, as this is usually the change - // from a transaction sent back to our own address. - continue; - } - - if (!std::get_if(&wtx.txout_address[nOut])) - { - // Sent to Bitcoin Address - sub.type = TransactionRecord::SendToAddress; - sub.address = EncodeDestination(wtx.txout_address[nOut]); - } - else - { - // Sent to IP, or other non-address transaction like OP_EVAL - sub.type = TransactionRecord::SendToOther; - sub.address = mapValue["to"]; - } - - CAmount nValue = txout.nValue; - /* Add fee to first output */ - if (nTxFee > 0) - { - nValue += nTxFee; - nTxFee = 0; - } - sub.debit = -nValue; - - parts.append(sub); - } - } - else - { - // - // Mixed debit transaction, can't break down payees - // - parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0)); - parts.last().involvesWatchAddress = involvesWatchAddress; - } + } else { + // + // Mixed debit transaction, can't break down payees + // + parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0)); + parts.last().involvesWatchAddress = involvesWatchAddress; } return parts; diff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp index 9083c304b2c..c027ff12401 100644 --- a/src/wallet/interfaces.cpp +++ b/src/wallet/interfaces.cpp @@ -64,6 +64,7 @@ WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx) result.txout_address_is_mine.reserve(wtx.tx->vout.size()); for (const auto& txout : wtx.tx->vout) { result.txout_is_mine.emplace_back(wallet.IsMine(txout)); + result.txout_is_change.push_back(OutputIsChange(wallet, txout)); result.txout_address.emplace_back(); result.txout_address_is_mine.emplace_back(ExtractDestination(txout.scriptPubKey, result.txout_address.back()) ? wallet.IsMine(result.txout_address.back()) :