Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

transactiondesc.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/transactiondesc.h>
7 
8 #include <qt/bitcoinunits.h>
9 #include <qt/guiutil.h>
10 #include <qt/paymentserver.h>
11 #include <qt/transactionrecord.h>
12 
13 #include <base58.h>
14 #include <consensus/consensus.h>
15 #include <validation.h>
16 #include <script/script.h>
17 #include <timedata.h>
18 #include <util.h>
19 #include <wallet/db.h>
20 #include <wallet/wallet.h>
21 
22 #include <stdint.h>
23 #include <string>
24 
26 {
28  if (!CheckFinalTx(*wtx.tx))
29  {
30  if (wtx.tx->nLockTime < LOCKTIME_THRESHOLD)
31  return tr("Open for %n more block(s)", "", wtx.tx->nLockTime - chainActive.Height());
32  else
33  return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.tx->nLockTime));
34  }
35  else
36  {
37  int nDepth = wtx.GetDepthInMainChain();
38  if (nDepth < 0) return tr("conflicted");
39 
40  QString strTxStatus;
41  bool fChainLocked = wtx.IsChainLocked();
42 
43  if (nDepth == 0) {
44  strTxStatus = tr("0/unconfirmed, %1").arg((wtx.InMempool() ? tr("in memory pool") : tr("not in memory pool"))) + (wtx.isAbandoned() ? ", "+tr("abandoned") : "");
45  } else if (!fChainLocked && nDepth < 6) {
46  strTxStatus = tr("%1/unconfirmed").arg(nDepth);
47  } else {
48  strTxStatus = tr("%1 confirmations").arg(nDepth);
49  if (fChainLocked) {
50  strTxStatus += ", " + tr("locked via ChainLocks");
51  return strTxStatus;
52  }
53  }
54 
55  if (wtx.IsLockedByInstantSend()) {
56  strTxStatus += ", " + tr("verified via InstantSend");
57  }
58 
59  return strTxStatus;
60  }
61 }
62 
63 QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionRecord *rec, int unit)
64 {
65  QString strHTML;
66 
67  LOCK2(cs_main, wallet->cs_wallet);
68  strHTML.reserve(4000);
69  strHTML += "<html>";
70 
71  int64_t nTime = wtx.GetTxTime();
72  CAmount nCredit = wtx.GetCredit(ISMINE_ALL);
73  CAmount nDebit = wtx.GetDebit(ISMINE_ALL);
74  CAmount nNet = nCredit - nDebit;
75 
76  strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx);
77  strHTML += "<br>";
78 
79  strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>";
80 
81  //
82  // From
83  //
84  if (wtx.IsCoinBase())
85  {
86  strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>";
87  }
88  else if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty())
89  {
90  // Online transaction
91  strHTML += "<b>" + tr("From") + ":</b> " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>";
92  }
93  else
94  {
95  // Offline transaction
96  if (nNet > 0)
97  {
98  // Credit
100  if (IsValidDestination(address)) {
101  if (wallet->mapAddressBook.count(address))
102  {
103  strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>";
104  strHTML += "<b>" + tr("To") + ":</b> ";
105  strHTML += GUIUtil::HtmlEscape(rec->strAddress);
106  QString addressOwned = (::IsMine(*wallet, address) == ISMINE_SPENDABLE) ? tr("own address") : tr("watch-only");
107  if (!wallet->mapAddressBook[address].name.empty())
108  strHTML += " (" + addressOwned + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")";
109  else
110  strHTML += " (" + addressOwned + ")";
111  strHTML += "<br>";
112  }
113  }
114  }
115  }
116 
117  //
118  // To
119  //
120  if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty())
121  {
122  // Online transaction
123  std::string strAddress = wtx.mapValue["to"];
124  strHTML += "<b>" + tr("To") + ":</b> ";
125  CTxDestination dest = DecodeDestination(strAddress);
126  if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].name.empty())
127  strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest].name) + " ";
128  strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
129  }
130 
131  //
132  // Amount
133  //
134  if (wtx.IsCoinBase() && nCredit == 0)
135  {
136  //
137  // Coinbase
138  //
139  CAmount nUnmatured = 0;
140  for (const CTxOut& txout : wtx.tx->vout)
141  nUnmatured += wallet->GetCredit(txout, ISMINE_ALL);
142  strHTML += "<b>" + tr("Credit") + ":</b> ";
143  if (wtx.IsInMainChain())
144  strHTML += BitcoinUnits::formatHtmlWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
145  else
146  strHTML += "(" + tr("not accepted") + ")";
147  strHTML += "<br>";
148  }
149  else if (nNet > 0)
150  {
151  //
152  // Credit
153  //
154  strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nNet) + "<br>";
155  }
156  else
157  {
158  isminetype fAllFromMe = ISMINE_SPENDABLE;
159  for (const CTxIn& txin : wtx.tx->vin)
160  {
161  isminetype mine = wallet->IsMine(txin);
162  if(fAllFromMe > mine) fAllFromMe = mine;
163  }
164 
165  isminetype fAllToMe = ISMINE_SPENDABLE;
166  for (const CTxOut& txout : wtx.tx->vout)
167  {
168  isminetype mine = wallet->IsMine(txout);
169  if(fAllToMe > mine) fAllToMe = mine;
170  }
171 
172  if (fAllFromMe)
173  {
174  if(fAllFromMe & ISMINE_WATCH_ONLY)
175  strHTML += "<b>" + tr("From") + ":</b> " + tr("watch-only") + "<br>";
176 
177  //
178  // Debit
179  //
180  for (const CTxOut& txout : wtx.tx->vout)
181  {
182  // Ignore change
183  isminetype toSelf = wallet->IsMine(txout);
184  if ((toSelf == ISMINE_SPENDABLE) && (fAllFromMe == ISMINE_SPENDABLE))
185  continue;
186 
187  if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty())
188  {
189  // Offline transaction
190  CTxDestination address;
191  if (ExtractDestination(txout.scriptPubKey, address))
192  {
193  strHTML += "<b>" + tr("To") + ":</b> ";
194  if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
195  strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
196  strHTML += GUIUtil::HtmlEscape(EncodeDestination(address));
197  if(toSelf == ISMINE_SPENDABLE)
198  strHTML += " (own address)";
199  else if(toSelf & ISMINE_WATCH_ONLY)
200  strHTML += " (watch-only)";
201  strHTML += "<br>";
202  }
203  }
204 
205  strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -txout.nValue) + "<br>";
206  if(toSelf)
207  strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, txout.nValue) + "<br>";
208  }
209 
210  if (fAllToMe)
211  {
212  // Payment to self
213  CAmount nChange = wtx.GetChange();
214  CAmount nValue = nCredit - nChange;
215  strHTML += "<b>" + tr("Total debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nValue) + "<br>";
216  strHTML += "<b>" + tr("Total credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nValue) + "<br>";
217  }
218 
219  CAmount nTxFee = nDebit - wtx.tx->GetValueOut();
220  if (nTxFee > 0)
221  strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nTxFee) + "<br>";
222  }
223  else
224  {
225  //
226  // Mixed debit transaction
227  //
228  for (const CTxIn& txin : wtx.tx->vin)
229  if (wallet->IsMine(txin))
230  strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "<br>";
231  for (const CTxOut& txout : wtx.tx->vout)
232  if (wallet->IsMine(txout))
233  strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "<br>";
234  }
235  }
236 
237  strHTML += "<b>" + tr("Net amount") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nNet, true) + "<br>";
238 
239  //
240  // Message
241  //
242  if (wtx.mapValue.count("message") && !wtx.mapValue["message"].empty())
243  strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "<br>";
244  if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty())
245  strHTML += "<br><b>" + tr("Comment") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
246 
247  strHTML += "<b>" + tr("Transaction ID") + ":</b> " + rec->getTxID() + "<br>";
248  strHTML += "<b>" + tr("Output index") + ":</b> " + QString::number(rec->getOutputIndex()) + "<br>";
249  strHTML += "<b>" + tr("Transaction total size") + ":</b> " + QString::number(wtx.tx->GetTotalSize()) + " bytes<br>";
250 
251  // Message from normal dash:URI (dash:XyZ...?message=example)
252  for (const std::pair<std::string, std::string>& r : wtx.vOrderForm)
253  if (r.first == "Message")
254  strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(r.second, true) + "<br>";
255 
256  //
257  // PaymentRequest info:
258  //
259  for (const std::pair<std::string, std::string>& r : wtx.vOrderForm)
260  {
261  if (r.first == "PaymentRequest")
262  {
263  PaymentRequestPlus req;
264  req.parse(QByteArray::fromRawData(r.second.data(), r.second.size()));
265  QString merchant;
266  if (req.getMerchant(PaymentServer::getCertStore(), merchant))
267  strHTML += "<b>" + tr("Merchant") + ":</b> " + GUIUtil::HtmlEscape(merchant) + "<br>";
268  }
269  }
270 
271  if (wtx.IsCoinBase())
272  {
273  quint32 numBlocksToMaturity = COINBASE_MATURITY + 1;
274  strHTML += "<br>" + tr("Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to \"not accepted\" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.").arg(QString::number(numBlocksToMaturity)) + "<br>";
275  }
276 
277  //
278  // Debug view
279  //
280  if (logCategories != BCLog::NONE)
281  {
282  strHTML += "<hr><br>" + tr("Debug information") + "<br><br>";
283  for (const CTxIn& txin : wtx.tx->vin)
284  if(wallet->IsMine(txin))
285  strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "<br>";
286  for (const CTxOut& txout : wtx.tx->vout)
287  if(wallet->IsMine(txout))
288  strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "<br>";
289 
290  strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
291  strHTML += GUIUtil::HtmlEscape(wtx.tx->ToString(), true);
292 
293  strHTML += "<br><b>" + tr("Inputs") + ":</b>";
294  strHTML += "<ul>";
295 
296  for (const CTxIn& txin : wtx.tx->vin)
297  {
298  COutPoint prevout = txin.prevout;
299 
300  Coin prev;
301  if(pcoinsTip->GetCoin(prevout, prev))
302  {
303  {
304  strHTML += "<li>";
305  const CTxOut& txout = prev.out;
306  CTxDestination address;
307  if (ExtractDestination(txout.scriptPubKey, address))
308  {
309  if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
310  strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
311  strHTML += QString::fromStdString(EncodeDestination(address));
312  }
313  strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatHtmlWithUnit(unit, txout.nValue);
314  strHTML = strHTML + " IsMine=" + (wallet->IsMine(txout) & ISMINE_SPENDABLE ? tr("true") : tr("false"));
315  strHTML = strHTML + " IsWatchOnly=" + (wallet->IsMine(txout) & ISMINE_WATCH_ONLY ? tr("true") : tr("false")) + "</li>";
316  }
317  }
318  }
319 
320  strHTML += "</ul>";
321  }
322 
323  strHTML += "</font></html>";
324  return strHTML;
325 }
CAmount nValue
Definition: transaction.h:147
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:80
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
CScript scriptPubKey
Definition: transaction.h:148
A UTXO entry.
Definition: coins.h:29
std::map< CTxDestination, CAddressBookData > mapAddressBook
Definition: wallet.h:906
CCriticalSection cs_wallet
Definition: wallet.h:836
bool IsChainLocked() const
Definition: wallet.cpp:5536
static QString formatHtmlWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as HTML string (with unit)
CAmount GetDebit(const isminefilter &filter) const
filter decides which addresses will count towards the debit
Definition: wallet.cpp:2169
int Height() const
Return the maximal height in the chain.
Definition: chain.h:484
CCriticalSection cs_main
Definition: validation.cpp:213
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:281
CTxOut out
unspent transaction output
Definition: coins.h:33
CTxDestination DecodeDestination(const std::string &str)
Definition: base58.cpp:336
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:258
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule) ...
Definition: consensus.h:24
QString HtmlEscape(const QString &str, bool fMultiLine)
Definition: guiutil.cpp:481
mapValue_t mapValue
Key/value map with information about the transaction.
Definition: wallet.h:311
std::unique_ptr< CCoinsViewCache > pcoinsTip
Global variable that points to the active CCoinsView (protected by cs_main)
Definition: validation.cpp:300
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
#define LOCK2(cs1, cs2)
Definition: sync.h:179
int getOutputIndex() const
Return the output index of the subtransaction.
UI model for a transaction.
bool CheckFinalTx(const CTransaction &tx, int flags)
Transaction validation functions.
Definition: validation.cpp:317
bool getMerchant(X509_STORE *certStore, QString &merchant) const
CTransactionRef tx
Definition: wallet.h:210
isminetype
IsMine() return codes.
Definition: ismine.h:17
An input of a transaction.
Definition: transaction.h:70
std::atomic< uint64_t > logCategories
bool InMempool() const
Definition: wallet.cpp:2414
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
An output of a transaction.
Definition: transaction.h:144
static X509_STORE * getCertStore()
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:26
bool parse(const QByteArray &data)
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
std::string EncodeDestination(const CTxDestination &dest)
Definition: base58.cpp:329
CAmount GetDebit(const CTxIn &txin, const isminefilter &filter) const
Returns amount of debit if the input matches the filter, otherwise returns 0.
Definition: wallet.cpp:1559
CAmount GetCredit(const isminefilter &filter) const
Definition: wallet.cpp:2200
int64_t GetTxTime() const
Definition: wallet.cpp:1923
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
Definition: wallet.h:715
static QString FormatTxStatus(const CWalletTx &wtx)
static const unsigned int LOCKTIME_THRESHOLD
Definition: script.h:39
CAmount GetCredit(const CTxOut &txout, const isminefilter &filter) const
Definition: wallet.cpp:1708
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
static QString toHTML(CWallet *wallet, CWalletTx &wtx, TransactionRecord *rec, int unit)
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
CAmount GetChange() const
Definition: wallet.cpp:2405
std::vector< std::pair< std::string, std::string > > vOrderForm
Definition: wallet.h:312
bool isAbandoned() const
Definition: wallet.h:269
Released under the MIT license