Bitcoin Core 22.99.0
P2P Digital Currency
transactionrecord.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-2020 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
6
7#include <chain.h>
8#include <interfaces/wallet.h>
9#include <key_io.h>
10#include <wallet/ismine.h>
11
12#include <stdint.h>
13
14#include <QDateTime>
15
16/* Return positive answer if transaction should be shown in list.
17 */
19{
20 // There are currently no cases where we hide transactions, but
21 // we may want to use this in the future for things like RBF.
22 return true;
23}
24
25/*
26 * Decompose CWallet transaction to model transaction records.
27 */
29{
30 QList<TransactionRecord> parts;
31 int64_t nTime = wtx.time;
32 CAmount nCredit = wtx.credit;
33 CAmount nDebit = wtx.debit;
34 CAmount nNet = nCredit - nDebit;
35 uint256 hash = wtx.tx->GetHash();
36 std::map<std::string, std::string> mapValue = wtx.value_map;
37
38 if (nNet > 0 || wtx.is_coinbase)
39 {
40 //
41 // Credit
42 //
43 for(unsigned int i = 0; i < wtx.tx->vout.size(); i++)
44 {
45 const CTxOut& txout = wtx.tx->vout[i];
46 isminetype mine = wtx.txout_is_mine[i];
47 if(mine)
48 {
49 TransactionRecord sub(hash, nTime);
50 sub.idx = i; // vout index
51 sub.credit = txout.nValue;
53 if (wtx.txout_address_is_mine[i])
54 {
55 // Received by Bitcoin Address
58 }
59 else
60 {
61 // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction
63 sub.address = mapValue["from"];
64 }
65 if (wtx.is_coinbase)
66 {
67 // Generated
69 }
70
71 parts.append(sub);
72 }
73 }
74 }
75 else
76 {
77 bool involvesWatchAddress = false;
78 isminetype fAllFromMe = ISMINE_SPENDABLE;
79 for (const isminetype mine : wtx.txin_is_mine)
80 {
82 if(fAllFromMe > mine) fAllFromMe = mine;
83 }
84
86 for (const isminetype mine : wtx.txout_is_mine)
87 {
89 if(fAllToMe > mine) fAllToMe = mine;
90 }
91
92 if (fAllFromMe && fAllToMe)
93 {
94 // Payment to self
95 std::string address;
96 for (auto it = wtx.txout_address.begin(); it != wtx.txout_address.end(); ++it) {
97 if (it != wtx.txout_address.begin()) address += ", ";
99 }
100
101 CAmount nChange = wtx.change;
102 parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, address, -(nDebit - nChange), nCredit - nChange));
103 parts.last().involvesWatchAddress = involvesWatchAddress; // maybe pass to TransactionRecord as constructor argument
104 }
105 else if (fAllFromMe)
106 {
107 //
108 // Debit
109 //
110 CAmount nTxFee = nDebit - wtx.tx->GetValueOut();
111
112 for (unsigned int nOut = 0; nOut < wtx.tx->vout.size(); nOut++)
113 {
114 const CTxOut& txout = wtx.tx->vout[nOut];
115 TransactionRecord sub(hash, nTime);
116 sub.idx = nOut;
118
119 if(wtx.txout_is_mine[nOut])
120 {
121 // Ignore parts sent to self, as this is usually the change
122 // from a transaction sent back to our own address.
123 continue;
124 }
125
126 if (!std::get_if<CNoDestination>(&wtx.txout_address[nOut]))
127 {
128 // Sent to Bitcoin Address
130 sub.address = EncodeDestination(wtx.txout_address[nOut]);
131 }
132 else
133 {
134 // Sent to IP, or other non-address transaction like OP_EVAL
136 sub.address = mapValue["to"];
137 }
138
139 CAmount nValue = txout.nValue;
140 /* Add fee to first output */
141 if (nTxFee > 0)
142 {
143 nValue += nTxFee;
144 nTxFee = 0;
145 }
146 sub.debit = -nValue;
147
148 parts.append(sub);
149 }
150 }
151 else
152 {
153 //
154 // Mixed debit transaction, can't break down payees
155 //
156 parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0));
157 parts.last().involvesWatchAddress = involvesWatchAddress;
158 }
159 }
160
161 return parts;
162}
163
164void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, const uint256& block_hash, int numBlocks, int64_t block_time)
165{
166 // Determine transaction status
167
168 // Sort order, unrecorded transactions sort to the top
169 status.sortKey = strprintf("%010d-%01d-%010u-%03d",
170 wtx.block_height,
171 wtx.is_coinbase ? 1 : 0,
172 wtx.time_received,
173 idx);
176 status.m_cur_block_hash = block_hash;
177
178 const bool up_to_date = ((int64_t)QDateTime::currentMSecsSinceEpoch() / 1000 - block_time < MAX_BLOCK_TIME_GAP);
179 if (up_to_date && !wtx.is_final) {
180 if (wtx.lock_time < LOCKTIME_THRESHOLD) {
182 status.open_for = wtx.lock_time - numBlocks;
183 }
184 else
185 {
188 }
189 }
190 // For generated transactions, determine maturity
192 {
193 if (wtx.blocks_to_maturity > 0)
194 {
196
197 if (wtx.is_in_main_chain)
198 {
200 }
201 else
202 {
204 }
205 }
206 else
207 {
209 }
210 }
211 else
212 {
213 if (status.depth < 0)
214 {
216 }
217 else if (status.depth == 0)
218 {
220 if (wtx.is_abandoned)
222 }
224 {
226 }
227 else
228 {
230 }
231 }
232 status.needsUpdate = false;
233}
234
236{
237 assert(!block_hash.IsNull());
238 return status.m_cur_block_hash != block_hash || status.needsUpdate;
239}
240
242{
243 return QString::fromStdString(hash.ToString());
244}
245
247{
248 return idx;
249}
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
static constexpr int64_t MAX_BLOCK_TIME_GAP
Maximum gap between node time and block time used for the "Catching up..." mode in GUI.
Definition: chain.h:38
An output of a transaction.
Definition: transaction.h:129
CAmount nValue
Definition: transaction.h:131
UI model for a transaction.
int idx
Subtransaction index, for sort key.
static QList< TransactionRecord > decomposeTransaction(const interfaces::WalletTx &wtx)
static const int RecommendedNumConfirmations
Number of confirmation recommended for accepting a transaction.
static bool showTransaction()
Decompose CWallet transaction to model transaction records.
TransactionStatus status
Status: can change with block chain update.
int getOutputIndex() const
Return the output index of the subtransaction
QString getTxHash() const
Return the unique identifier for this transaction (part)
bool statusUpdateNeeded(const uint256 &block_hash) const
Return whether a status update is needed.
void updateStatus(const interfaces::WalletTxStatus &wtx, const uint256 &block_hash, int numBlocks, int64_t block_time)
Update status from core wallet tx.
bool involvesWatchAddress
Whether the transaction was sent/received with a watch-only address.
bool countsForBalance
Transaction counts towards available balance.
uint256 m_cur_block_hash
Current block hash (to know whether cached status is still valid)
qint64 open_for
Timestamp if status==OpenUntilDate, otherwise number of additional blocks that need to be mined befor...
@ Confirmed
Have 6 or more confirmations (normal tx) or fully mature (mined tx)
@ OpenUntilDate
Normal (sent/received) transactions.
@ Unconfirmed
Not yet mined into a block.
@ Immature
Generated (mined) transactions.
@ Confirming
Confirmed, but waiting for the recommended number of confirmations.
@ NotAccepted
Mined but not accepted.
@ OpenUntilBlock
Transaction not yet final, waiting for block.
@ Conflicted
Conflicts with other transaction or mempool.
@ Abandoned
Abandoned from the wallet.
std::string sortKey
Sorting key based on status.
std::string ToString() const
Definition: uint256.cpp:64
bool IsNull() const
Definition: uint256.h:31
256-bit opaque blob.
Definition: uint256.h:124
isminetype
IsMine() return codes, which depend on ScriptPubKeyMan implementation.
Definition: ismine.h:39
@ ISMINE_SPENDABLE
Definition: ismine.h:42
@ ISMINE_WATCH_ONLY
Definition: ismine.h:41
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:256
static const unsigned int LOCKTIME_THRESHOLD
Definition: script.h:40
std::vector< CTxDestination > txout_address
Definition: wallet.h:380
std::vector< isminetype > txout_is_mine
Definition: wallet.h:379
CTransactionRef tx
Definition: wallet.h:377
std::map< std::string, std::string > value_map
Definition: wallet.h:386
std::vector< isminetype > txout_address_is_mine
Definition: wallet.h:381
std::vector< isminetype > txin_is_mine
Definition: wallet.h:378
Updated transaction status.
Definition: wallet.h:392
unsigned int time_received
Definition: wallet.h:396
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164
assert(!tx.IsCoinBase())