Bitcoin Core  0.20.99
P2P Digital Currency
transactionrecord.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2019 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 
5 #include <qt/transactionrecord.h>
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  {
81  if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true;
82  if(fAllFromMe > mine) fAllFromMe = mine;
83  }
84 
85  isminetype fAllToMe = ISMINE_SPENDABLE;
86  for (const isminetype mine : wtx.txout_is_mine)
87  {
88  if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true;
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 += ", ";
98  address += EncodeDestination(*it);
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 (!boost::get<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 
164 void 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  {
187  status.open_for = wtx.lock_time;
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 
235 bool TransactionRecord::statusUpdateNeeded(const uint256& block_hash) const
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 }
bool statusUpdateNeeded(const uint256 &block_hash) const
Return whether a status update is needed.
CAmount nValue
Definition: transaction.h:131
Confirmed, but waiting for the recommended number of confirmations.
std::deque< CInv >::iterator it
std::vector< CTxDestination > txout_address
Definition: wallet.h:374
Transaction not yet final, waiting for block.
int idx
Subtransaction index, for sort key.
unsigned int time_received
Definition: wallet.h:390
QString getTxHash() const
Return the unique identifier for this transaction (part)
Generated (mined) transactions.
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164
std::vector< isminetype > txin_is_mine
Definition: wallet.h:372
std::vector< isminetype > txout_is_mine
Definition: wallet.h:373
Have 6 or more confirmations (normal tx) or fully mature (mined tx)
std::string sortKey
Sorting key based on status.
static QList< TransactionRecord > decomposeTransaction(const interfaces::WalletTx &wtx)
Mined but not accepted.
Not yet mined into a block.
CTransactionRef tx
Definition: wallet.h:371
bool IsNull() const
Definition: uint256.h:31
void updateStatus(const interfaces::WalletTxStatus &wtx, const uint256 &block_hash, int numBlocks, int64_t block_time)
Update status from core wallet tx.
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
int getOutputIndex() const
Return the output index of the subtransaction.
UI model for a transaction.
uint256 m_cur_block_hash
Current block hash (to know whether cached status is still valid)
TransactionStatus status
Status: can change with block chain update.
bool countsForBalance
Transaction counts towards available balance.
isminetype
IsMine() return codes.
Definition: ismine.h:18
An output of a transaction.
Definition: transaction.h:128
std::string ToString() const
Definition: uint256.cpp:64
Normal (sent/received) transactions.
static bool showTransaction()
Decompose CWallet transaction to model transaction records.
256-bit opaque blob.
Definition: uint256.h:124
std::vector< isminetype > txout_address_is_mine
Definition: wallet.h:375
Conflicts with other transaction or mempool.
bool involvesWatchAddress
Whether the transaction was sent/received with a watch-only address.
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:210
std::map< std::string, std::string > value_map
Definition: wallet.h:380
static const unsigned int LOCKTIME_THRESHOLD
Definition: script.h:39
qint64 open_for
Timestamp if status==OpenUntilDate, otherwise number of additional blocks that need to be mined befor...
Abandoned from the wallet.
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
Updated transaction status.
Definition: wallet.h:385
static const int RecommendedNumConfirmations
Number of confirmation recommended for accepting a transaction.