diff options
author | Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> | 2023-09-22 18:26:15 +0100 |
---|---|---|
committer | Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> | 2023-09-22 18:29:51 +0100 |
commit | b000ed5ee54438efb72e190262faeb535489d35d (patch) | |
tree | ff5bb03ac764ac471c7770da0659046949e483ac /src/qt/transactionrecord.cpp | |
parent | bce7b087cbd9668f46b5c560f3187db2e878a2df (diff) | |
parent | 099dbe4224e0e896604e7f6901d0fc302b0bd3a0 (diff) |
Merge bitcoin-core/gui#119: Replace send-to-self with dual send+receive entries
099dbe4224e0e896604e7f6901d0fc302b0bd3a0 GUI: TransactionRecord: When time/index/etc match, sort send before receive (Luke Dashjr)
2d182f77cd8100395cf47a721bd01dc8620c9718 Bugfix: Ignore ischange flag when we're not the sender (Luke Dashjr)
71fbdb7f403e673877be94a79cd4c6b13b0bbcd6 GUI: Remove SendToSelf TransactionRecord type (Luke Dashjr)
f3fbe99fcf90daec79d49fd5d868102dc99feb23 GUI: TransactionRecord: Refactor to turn send-to-self into send+receive pairs (Luke Dashjr)
b9765ba1d67d7b74c17f9ce70cad5487715208a0 GUI: TransactionRecord: Use "any from me" as the criteria for deciding whether a transaction is a send or receive (Luke Dashjr)
Pull request description:
Makes the GUI transaction list more like the RPC, and IMO clearer in general.
As a side effect, this also fixes the GUI entries when a transaction is a net profit to us, but some inputs were also from us.
Originally https://github.com/bitcoin/bitcoin/pull/15115
Has Concept ACKs from @*Empact @*jonasschnelli
ACKs for top commit:
hebasto:
ACK 099dbe4224e0e896604e7f6901d0fc302b0bd3a0.
Tree-SHA512: 7d581add2f59431aa019126d54232a1f15723def5147d7a1b672e9b6d525b6e5a944cc437701aa1bd5bd0fbe557a3d1f4b239337f42bdba4fe1d3960442d0e3b
Diffstat (limited to 'src/qt/transactionrecord.cpp')
-rw-r--r-- | src/qt/transactionrecord.cpp | 160 |
1 files changed, 77 insertions, 83 deletions
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 1d2f6484fb..8a2ec4cd59 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -13,6 +13,7 @@ #include <QDateTime> +using wallet::ISMINE_NO; using wallet::ISMINE_SPENDABLE; using wallet::ISMINE_WATCH_ONLY; using wallet::isminetype; @@ -39,99 +40,52 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const interface uint256 hash = wtx.tx->GetHash(); std::map<std::string, std::string> mapValue = wtx.value_map; - if (nNet > 0 || wtx.is_coinbase) - { - // - // Credit - // - for(unsigned int i = 0; i < wtx.tx->vout.size(); i++) - { - const CTxOut& txout = wtx.tx->vout[i]; - isminetype mine = wtx.txout_is_mine[i]; - if(mine) - { - TransactionRecord sub(hash, nTime); - sub.idx = i; // vout index - sub.credit = txout.nValue; - sub.involvesWatchAddress = mine & ISMINE_WATCH_ONLY; - if (wtx.txout_address_is_mine[i]) - { - // Received by Bitcoin Address - sub.type = TransactionRecord::RecvWithAddress; - sub.address = EncodeDestination(wtx.txout_address[i]); - } - else - { - // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction - sub.type = TransactionRecord::RecvFromOther; - sub.address = mapValue["from"]; - } - if (wtx.is_coinbase) - { - // Generated - sub.type = TransactionRecord::Generated; - } - - parts.append(sub); - } - } - } - else - { - bool involvesWatchAddress = false; - isminetype fAllFromMe = ISMINE_SPENDABLE; + bool involvesWatchAddress = false; + isminetype fAllFromMe = ISMINE_SPENDABLE; + bool any_from_me = false; + if (wtx.is_coinbase) { + fAllFromMe = ISMINE_NO; + } else { for (const isminetype mine : wtx.txin_is_mine) { if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true; if(fAllFromMe > mine) fAllFromMe = mine; + if (mine) any_from_me = true; } + } - isminetype fAllToMe = ISMINE_SPENDABLE; + if (fAllFromMe || !any_from_me) { 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 nTxFee = nDebit - wtx.tx->GetValueOut(); - 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) + for(unsigned int i = 0; i < wtx.tx->vout.size(); i++) { - // - // 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; + const CTxOut& txout = wtx.tx->vout[i]; - 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. + if (fAllFromMe) { + // Change is only really possible if we're the sender + // Otherwise, someone just sent bitcoins to a change address, which should be shown + if (wtx.txout_is_change[i]) { continue; } - if (!std::get_if<CNoDestination>(&wtx.txout_address[nOut])) + // + // Debit + // + + TransactionRecord sub(hash, nTime); + sub.idx = i; + sub.involvesWatchAddress = involvesWatchAddress; + + if (!std::get_if<CNoDestination>(&wtx.txout_address[i])) { // Sent to Bitcoin Address sub.type = TransactionRecord::SendToAddress; - sub.address = EncodeDestination(wtx.txout_address[nOut]); + sub.address = EncodeDestination(wtx.txout_address[i]); } else { @@ -151,15 +105,45 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const interface 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; + sub.involvesWatchAddress = mine & ISMINE_WATCH_ONLY; + if (wtx.txout_address_is_mine[i]) + { + // Received by Bitcoin Address + sub.type = TransactionRecord::RecvWithAddress; + sub.address = EncodeDestination(wtx.txout_address[i]); + } + else + { + // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction + sub.type = TransactionRecord::RecvFromOther; + sub.address = mapValue["from"]; + } + if (wtx.is_coinbase) + { + // Generated + sub.type = TransactionRecord::Generated; + } + + 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; @@ -170,11 +154,21 @@ void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, cons // Determine transaction status // Sort order, unrecorded transactions sort to the top - status.sortKey = strprintf("%010d-%01d-%010u-%03d", + int typesort; + switch (type) { + case SendToAddress: case SendToOther: + typesort = 2; break; + case RecvWithAddress: case RecvFromOther: + typesort = 3; break; + default: + typesort = 9; + } + status.sortKey = strprintf("%010d-%01d-%010u-%03d-%d", wtx.block_height, wtx.is_coinbase ? 1 : 0, wtx.time_received, - idx); + idx, + typesort); status.countsForBalance = wtx.is_trusted && !(wtx.blocks_to_maturity > 0); status.depth = wtx.depth_in_main_chain; status.m_cur_block_hash = block_hash; |