Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

transactionrecord.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2015 The Bitcoin Core developers
2 // Copyright (c) 2014-2019 The Dash Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <qt/transactionrecord.h>
7 
8 #include <base58.h>
9 #include <consensus/consensus.h>
10 #include <validation.h>
11 #include <timedata.h>
12 #include <wallet/wallet.h>
13 
15 
16 #include <stdint.h>
17 
18 
19 /* Return positive answer if transaction should be shown in list.
20  */
22 {
23  // There are currently no cases where we hide transactions, but
24  // we may want to use this in the future for things like RBF.
25  return true;
26 }
27 
28 /*
29  * Decompose CWallet transaction to model transaction records.
30  */
31 QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
32 {
33  QList<TransactionRecord> parts;
34  int64_t nTime = wtx.GetTxTime();
35  CAmount nCredit = wtx.GetCredit(ISMINE_ALL);
36  CAmount nDebit = wtx.GetDebit(ISMINE_ALL);
37  CAmount nNet = nCredit - nDebit;
38  uint256 hash = wtx.GetHash();
39  std::map<std::string, std::string> mapValue = wtx.mapValue;
40 
41  if (nNet > 0 || wtx.IsCoinBase())
42  {
43  //
44  // Credit
45  //
46  for(unsigned int i = 0; i < wtx.tx->vout.size(); i++)
47  {
48  const CTxOut& txout = wtx.tx->vout[i];
49  isminetype mine = wallet->IsMine(txout);
50  if(mine)
51  {
52  TransactionRecord sub(hash, nTime);
53  CTxDestination address;
54  sub.idx = i; // vout index
55  sub.credit = txout.nValue;
57  if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
58  {
59  // Received by Dash Address
61  sub.strAddress = EncodeDestination(address);
62  sub.txDest = address;
63  }
64  else
65  {
66  // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction
68  sub.strAddress = mapValue["from"];
70  }
71  if (wtx.IsCoinBase())
72  {
73  // Generated
75  }
76 
77  parts.append(sub);
78  }
79  }
80  }
81  else
82  {
83  bool fAllFromMeDenom = true;
84  int nFromMe = 0;
85  bool involvesWatchAddress = false;
86  isminetype fAllFromMe = ISMINE_SPENDABLE;
87  for (const CTxIn& txin : wtx.tx->vin)
88  {
89  if(wallet->IsMine(txin)) {
90  fAllFromMeDenom = fAllFromMeDenom && wallet->IsDenominated(txin.prevout);
91  nFromMe++;
92  }
93  isminetype mine = wallet->IsMine(txin);
94  if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true;
95  if(fAllFromMe > mine) fAllFromMe = mine;
96  }
97 
98  isminetype fAllToMe = ISMINE_SPENDABLE;
99  bool fAllToMeDenom = true;
100  int nToMe = 0;
101  for (const CTxOut& txout : wtx.tx->vout) {
102  if(wallet->IsMine(txout)) {
103  fAllToMeDenom = fAllToMeDenom && CPrivateSend::IsDenominatedAmount(txout.nValue);
104  nToMe++;
105  }
106  isminetype mine = wallet->IsMine(txout);
107  if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true;
108  if(fAllToMe > mine) fAllToMe = mine;
109  }
110 
111  if(fAllFromMeDenom && fAllToMeDenom && nFromMe * nToMe) {
112  parts.append(TransactionRecord(hash, nTime, TransactionRecord::PrivateSendDenominate, "", -nDebit, nCredit));
113  parts.last().involvesWatchAddress = false; // maybe pass to TransactionRecord as constructor argument
114  }
115  else if (fAllFromMe && fAllToMe)
116  {
117  // Payment to self
118  // TODO: this section still not accurate but covers most cases,
119  // might need some additional work however
120 
121  TransactionRecord sub(hash, nTime);
122  // Payment to self by default
124  sub.strAddress = "";
125 
126  if(mapValue["DS"] == "1")
127  {
129  CTxDestination address;
130  if (ExtractDestination(wtx.tx->vout[0].scriptPubKey, address))
131  {
132  // Sent to Dash Address
133  sub.strAddress = EncodeDestination(address);
134  sub.txDest = address;
135  }
136  else
137  {
138  // Sent to IP, or other non-address transaction like OP_EVAL
139  sub.strAddress = mapValue["to"];
141  }
142  }
143  else
144  {
145  sub.idx = parts.size();
146  if(wtx.tx->vin.size() == 1 && wtx.tx->vout.size() == 1
150  {
152  } else {
153  bool fMakeCollateral{false};
154  if (wtx.tx->vout.size() == 2) {
155  CAmount nAmount0 = wtx.tx->vout[0].nValue;
156  CAmount nAmount1 = wtx.tx->vout[1].nValue;
157  // <case1>, see CPrivateSendClientSession::MakeCollateralAmounts
158  fMakeCollateral = (nAmount0 == CPrivateSend::GetMaxCollateralAmount() && !CPrivateSend::IsDenominatedAmount(nAmount1) && nAmount1 >= CPrivateSend::GetCollateralAmount()) ||
160  // <case2>, see CPrivateSendClientSession::MakeCollateralAmounts
161  (nAmount0 == nAmount1 && CPrivateSend::IsCollateralAmount(nAmount0));
162  } else if (wtx.tx->vout.size() == 1) {
163  // <case3>, see CPrivateSendClientSession::MakeCollateralAmounts
164  fMakeCollateral = CPrivateSend::IsCollateralAmount(wtx.tx->vout[0].nValue);
165  }
166  if (fMakeCollateral) {
168  } else {
169  for (const auto& txout : wtx.tx->vout) {
172  break; // Done, it's definitely a tx creating mixing denoms, no need to look any further
173  }
174  }
175  }
176  }
177  }
178 
179  CAmount nChange = wtx.GetChange();
180 
181  sub.debit = -(nDebit - nChange);
182  sub.credit = nCredit - nChange;
183  parts.append(sub);
184  parts.last().involvesWatchAddress = involvesWatchAddress; // maybe pass to TransactionRecord as constructor argument
185  }
186  else if (fAllFromMe)
187  {
188  //
189  // Debit
190  //
191  CAmount nTxFee = nDebit - wtx.tx->GetValueOut();
192 
193  bool fDone = false;
194  if(wtx.tx->vin.size() == 1 && wtx.tx->vout.size() == 1
196  && nCredit == 0 // OP_RETURN
198  {
199  TransactionRecord sub(hash, nTime);
200  sub.idx = 0;
202  sub.debit = -nDebit;
203  parts.append(sub);
204  fDone = true;
205  }
206 
207  for (unsigned int nOut = 0; nOut < wtx.tx->vout.size() && !fDone; nOut++)
208  {
209  const CTxOut& txout = wtx.tx->vout[nOut];
210  TransactionRecord sub(hash, nTime);
211  sub.idx = nOut;
213 
214  if(wallet->IsMine(txout))
215  {
216  // Ignore parts sent to self, as this is usually the change
217  // from a transaction sent back to our own address.
218  continue;
219  }
220 
221  CTxDestination address;
222  if (ExtractDestination(txout.scriptPubKey, address))
223  {
224  // Sent to Dash Address
226  sub.strAddress = EncodeDestination(address);
227  sub.txDest = address;
228  }
229  else
230  {
231  // Sent to IP, or other non-address transaction like OP_EVAL
233  sub.strAddress = mapValue["to"];
235  }
236 
237  if(mapValue["DS"] == "1")
238  {
240  }
241 
242  CAmount nValue = txout.nValue;
243  /* Add fee to first output */
244  if (nTxFee > 0)
245  {
246  nValue += nTxFee;
247  nTxFee = 0;
248  }
249  sub.debit = -nValue;
250 
251  parts.append(sub);
252  }
253  }
254  else
255  {
256  //
257  // Mixed debit transaction, can't break down payees
258  //
259  parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0));
260  parts.last().involvesWatchAddress = involvesWatchAddress;
261  }
262  }
263 
264  return parts;
265 }
266 
267 void TransactionRecord::updateStatus(const CWalletTx &wtx, int chainLockHeight)
268 {
271  // Determine transaction status
272 
273  // Find the block the tx is in
274  CBlockIndex* pindex = nullptr;
275  BlockMap::iterator mi = mapBlockIndex.find(wtx.hashBlock);
276  if (mi != mapBlockIndex.end())
277  pindex = (*mi).second;
278 
279  // Sort order, unrecorded transactions sort to the top
280  status.sortKey = strprintf("%010d-%01d-%010u-%03d",
281  (pindex ? pindex->nHeight : std::numeric_limits<int>::max()),
282  (wtx.IsCoinBase() ? 1 : 0),
283  wtx.nTimeReceived,
284  idx);
285  status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0);
288  status.cachedChainLockHeight = chainLockHeight;
289 
290  bool oldLockedByChainLocks = status.lockedByChainLocks;
291  if (!status.lockedByChainLocks) {
293  }
294 
295  auto addrBookIt = wtx.GetWallet()->mapAddressBook.find(this->txDest);
296  if (addrBookIt == wtx.GetWallet()->mapAddressBook.end()) {
297  status.label = "";
298  } else {
299  status.label = QString::fromStdString(addrBookIt->second.name);
300  }
301 
302  if (!CheckFinalTx(*wtx.tx))
303  {
304  if (wtx.tx->nLockTime < LOCKTIME_THRESHOLD)
305  {
307  status.open_for = wtx.tx->nLockTime - chainActive.Height();
308  }
309  else
310  {
312  status.open_for = wtx.tx->nLockTime;
313  }
314  }
315  // For generated transactions, determine maturity
317  {
318  if (wtx.GetBlocksToMaturity() > 0)
319  {
321 
322  if (wtx.IsInMainChain())
323  {
325  }
326  else
327  {
329  }
330  }
331  else
332  {
334  }
335  }
336  else
337  {
338  // The IsLockedByInstantSend call is quite expensive, so we only do it when a state change is actually possible.
340  if (oldLockedByChainLocks != status.lockedByChainLocks) {
342  } else {
343  status.lockedByInstantSend = false;
344  }
345  } else if (!status.lockedByInstantSend) {
347  }
348 
349  if (status.depth < 0)
350  {
352  }
353  else if (status.depth == 0)
354  {
356  if (wtx.isAbandoned())
358  }
360  {
362  }
363  else
364  {
366  }
367  }
368  status.needsUpdate = false;
369 }
370 
371 bool TransactionRecord::statusUpdateNeeded(int chainLockHeight) const
372 {
375  || (!status.lockedByChainLocks && status.cachedChainLockHeight != chainLockHeight);
376 }
377 
379 {
380  return QString::fromStdString(hash.ToString());
381 }
382 
384 {
385  return idx;
386 }
CAmount nValue
Definition: transaction.h:147
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:80
Confirmed, but waiting for the recommended number of confirmations.
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:158
bool IsLockedByInstantSend() const
Definition: wallet.cpp:5531
Transaction not yet final, waiting for block.
int idx
Subtransaction index, for sort key.
static bool IsDenominatedAmount(CAmount nInputAmount)
CScript scriptPubKey
Definition: transaction.h:148
static CAmount GetCollateralAmount()
Definition: privatesend.h:460
std::map< CTxDestination, CAddressBookData > mapAddressBook
Definition: wallet.h:906
CCriticalSection cs_wallet
Definition: wallet.h:836
Generated (mined) transactions.
#define strprintf
Definition: tinyformat.h:1066
const uint256 & GetHash() const
Definition: wallet.h:272
BlockMap & mapBlockIndex
Definition: validation.cpp:215
bool IsChainLocked() const
Definition: wallet.cpp:5536
CAmount GetDebit(const isminefilter &filter) const
filter decides which addresses will count towards the debit
Definition: wallet.cpp:2169
Have 6 or more confirmations (normal tx) or fully mature (mined tx)
std::string sortKey
Sorting key based on status.
int Height() const
Return the maximal height in the chain.
Definition: chain.h:484
uint256 hashBlock
Definition: wallet.h:211
CCriticalSection cs_main
Definition: validation.cpp:213
CTxDestination DecodeDestination(const std::string &str)
Definition: base58.cpp:336
QString label
Label.
Mined but not accepted.
Not yet mined into a block.
void updateStatus(const CWalletTx &wtx, int chainLockHeight)
Update status from core wallet tx.
static bool showTransaction(const CWalletTx &wtx)
Decompose CWallet transaction to model transaction records.
mapValue_t mapValue
Key/value map with information about the transaction.
Definition: wallet.h:311
bool lockedByChainLocks
Transaction was locked via ChainLocks.
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
int getOutputIndex() const
Return the output index of the subtransaction.
CTxDestination txDest
UI model for a transaction.
bool CheckFinalTx(const CTransaction &tx, int flags)
Transaction validation functions.
Definition: validation.cpp:317
TransactionStatus status
Status: can change with block chain update.
static QList< TransactionRecord > decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
CTransactionRef tx
Definition: wallet.h:210
isminetype
IsMine() return codes.
Definition: ismine.h:17
An input of a transaction.
Definition: transaction.h:70
bool IsDenominated(const COutPoint &outpoint) const
Definition: wallet.cpp:1664
QString getTxID() const
Return the unique identifier for this transaction (part)
bool IsCoinBase() const
Definition: wallet.h:273
int GetBlocksToMaturity() const
Definition: wallet.cpp:5546
bool countsForBalance
Transaction counts towards available balance.
bool IsTrusted() const
Definition: wallet.cpp:2419
An output of a transaction.
Definition: transaction.h:144
std::string ToString() const
Definition: uint256.cpp:62
int cur_num_blocks
Current number of blocks (to know whether cached status is still valid)
Normal (sent/received) transactions.
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:280
bool IsInMainChain() const
Definition: wallet.h:264
256-bit opaque blob.
Definition: uint256.h:123
std::string EncodeDestination(const CTxDestination &dest)
Definition: base58.cpp:329
CAmount GetCredit(const isminefilter &filter) const
Definition: wallet.cpp:2200
int64_t GetTxTime() const
Definition: wallet.cpp:1923
const CWallet * GetWallet() const
Definition: wallet.h:476
Conflicts with other transaction or mempool.
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:170
bool lockedByInstantSend
Transaction was locked via InstantSend.
bool involvesWatchAddress
Whether the transaction was sent/received with a watch-only address.
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
Definition: wallet.h:715
static CAmount GetMaxCollateralAmount()
Definition: privatesend.h:461
static bool IsCollateralAmount(CAmount nInputAmount)
bool statusUpdateNeeded(int chainLockHeight) const
Return whether a status update is needed.
unsigned int nTimeReceived
time received by this node
Definition: wallet.h:314
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...
isminetype IsMine(const CTxIn &txin) const
Definition: wallet.cpp:1542
CChain & chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:217
AssertLockHeld(g_cs_orphans)
COutPoint prevout
Definition: transaction.h:73
Abandoned from the wallet.
int GetDepthInMainChain(const CBlockIndex *&pindexRet) const
Return depth of transaction in blockchain: <0 : conflicts with a transaction this deep in the blockch...
Definition: wallet.cpp:5501
isminetype IsMine(const CKeyStore &keystore, const CTxDestination &dest)
Definition: ismine.cpp:28
static const int RecommendedNumConfirmations
Number of confirmation recommended for accepting a transaction.
CAmount GetChange() const
Definition: wallet.cpp:2405
bool isAbandoned() const
Definition: wallet.h:269
Released under the MIT license