aboutsummaryrefslogtreecommitdiff
path: root/src/qt/transactionrecord.cpp
diff options
context:
space:
mode:
authorHennadii Stepanov <32963518+hebasto@users.noreply.github.com>2023-09-22 18:26:15 +0100
committerHennadii Stepanov <32963518+hebasto@users.noreply.github.com>2023-09-22 18:29:51 +0100
commitb000ed5ee54438efb72e190262faeb535489d35d (patch)
treeff5bb03ac764ac471c7770da0659046949e483ac /src/qt/transactionrecord.cpp
parentbce7b087cbd9668f46b5c560f3187db2e878a2df (diff)
parent099dbe4224e0e896604e7f6901d0fc302b0bd3a0 (diff)
downloadbitcoin-b000ed5ee54438efb72e190262faeb535489d35d.tar.xz
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.cpp160
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;