]> Git Repo - VerusCoin.git/blob - src/qt/transactiondesc.cpp
Move CScript class and dependencies to script/script
[VerusCoin.git] / src / qt / transactiondesc.cpp
1 // Copyright (c) 2011-2014 The Bitcoin developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5 #include "transactiondesc.h"
6
7 #include "bitcoinunits.h"
8 #include "guiutil.h"
9
10 #include "base58.h"
11 #include "db.h"
12 #include "main.h"
13 #include "paymentserver.h"
14 #include "script/script.h"
15 #include "transactionrecord.h"
16 #include "timedata.h"
17 #include "ui_interface.h"
18 #include "util.h"
19 #include "wallet.h"
20
21 #include <stdint.h>
22 #include <string>
23
24 using namespace std;
25
26 QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
27 {
28     AssertLockHeld(cs_main);
29     if (!IsFinalTx(wtx, chainActive.Height() + 1))
30     {
31         if (wtx.nLockTime < LOCKTIME_THRESHOLD)
32             return tr("Open for %n more block(s)", "", wtx.nLockTime - chainActive.Height());
33         else
34             return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime));
35     }
36     else
37     {
38         int nDepth = wtx.GetDepthInMainChain();
39         if (nDepth < 0)
40             return tr("conflicted");
41         else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
42             return tr("%1/offline").arg(nDepth);
43         else if (nDepth < 6)
44             return tr("%1/unconfirmed").arg(nDepth);
45         else
46             return tr("%1 confirmations").arg(nDepth);
47     }
48 }
49
50 QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionRecord *rec, int unit)
51 {
52     QString strHTML;
53
54     LOCK2(cs_main, wallet->cs_wallet);
55     strHTML.reserve(4000);
56     strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
57
58     int64_t nTime = wtx.GetTxTime();
59     int64_t nCredit = wtx.GetCredit(ISMINE_ALL);
60     int64_t nDebit = wtx.GetDebit(ISMINE_ALL);
61     int64_t nNet = nCredit - nDebit;
62
63     strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx);
64     int nRequests = wtx.GetRequestCount();
65     if (nRequests != -1)
66     {
67         if (nRequests == 0)
68             strHTML += tr(", has not been successfully broadcast yet");
69         else if (nRequests > 0)
70             strHTML += tr(", broadcast through %n node(s)", "", nRequests);
71     }
72     strHTML += "<br>";
73
74     strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>";
75
76     //
77     // From
78     //
79     if (wtx.IsCoinBase())
80     {
81         strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>";
82     }
83     else if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty())
84     {
85         // Online transaction
86         strHTML += "<b>" + tr("From") + ":</b> " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>";
87     }
88     else
89     {
90         // Offline transaction
91         if (nNet > 0)
92         {
93             // Credit
94             if (CBitcoinAddress(rec->address).IsValid())
95             {
96                 CTxDestination address = CBitcoinAddress(rec->address).Get();
97                 if (wallet->mapAddressBook.count(address))
98                 {
99                     strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>";
100                     strHTML += "<b>" + tr("To") + ":</b> ";
101                     strHTML += GUIUtil::HtmlEscape(rec->address);
102                     QString addressOwned = (::IsMine(*wallet, address) == ISMINE_SPENDABLE) ? tr("own address") : tr("watch-only");
103                     if (!wallet->mapAddressBook[address].name.empty())
104                         strHTML += " (" + addressOwned + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")";
105                     else
106                         strHTML += " (" + addressOwned + ")";
107                     strHTML += "<br>";
108                 }
109             }
110         }
111     }
112
113     //
114     // To
115     //
116     if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty())
117     {
118         // Online transaction
119         std::string strAddress = wtx.mapValue["to"];
120         strHTML += "<b>" + tr("To") + ":</b> ";
121         CTxDestination dest = CBitcoinAddress(strAddress).Get();
122         if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].name.empty())
123             strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest].name) + " ";
124         strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
125     }
126
127     //
128     // Amount
129     //
130     if (wtx.IsCoinBase() && nCredit == 0)
131     {
132         //
133         // Coinbase
134         //
135         int64_t nUnmatured = 0;
136         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
137             nUnmatured += wallet->GetCredit(txout, ISMINE_ALL);
138         strHTML += "<b>" + tr("Credit") + ":</b> ";
139         if (wtx.IsInMainChain())
140             strHTML += BitcoinUnits::formatHtmlWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
141         else
142             strHTML += "(" + tr("not accepted") + ")";
143         strHTML += "<br>";
144     }
145     else if (nNet > 0)
146     {
147         //
148         // Credit
149         //
150         strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nNet) + "<br>";
151     }
152     else
153     {
154         isminetype fAllFromMe = ISMINE_SPENDABLE;
155         BOOST_FOREACH(const CTxIn& txin, wtx.vin)
156         {
157             isminetype mine = wallet->IsMine(txin);
158             if(fAllFromMe > mine) fAllFromMe = mine;
159         }
160
161         isminetype fAllToMe = ISMINE_SPENDABLE;
162         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
163         {
164             isminetype mine = wallet->IsMine(txout);
165             if(fAllToMe > mine) fAllToMe = mine;
166         }
167
168         if (fAllFromMe)
169         {
170             if(fAllFromMe == ISMINE_WATCH_ONLY)
171                 strHTML += "<b>" + tr("From") + ":</b> " + tr("watch-only") + "<br>";
172
173             //
174             // Debit
175             //
176             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
177             {
178                 // Ignore change
179                 isminetype toSelf = wallet->IsMine(txout);
180                 if ((toSelf == ISMINE_SPENDABLE) && (fAllFromMe == ISMINE_SPENDABLE))
181                     continue;
182
183                 if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty())
184                 {
185                     // Offline transaction
186                     CTxDestination address;
187                     if (ExtractDestination(txout.scriptPubKey, address))
188                     {
189                         strHTML += "<b>" + tr("To") + ":</b> ";
190                         if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
191                             strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
192                         strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
193                         if(toSelf == ISMINE_SPENDABLE)
194                             strHTML += " (own address)";
195                         else if(toSelf == ISMINE_WATCH_ONLY)
196                             strHTML += " (watch-only)";
197                         strHTML += "<br>";
198                     }
199                 }
200
201                 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -txout.nValue) + "<br>";
202                 if(toSelf)
203                     strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, txout.nValue) + "<br>";
204             }
205
206             if (fAllToMe)
207             {
208                 // Payment to self
209                 int64_t nChange = wtx.GetChange();
210                 int64_t nValue = nCredit - nChange;
211                 strHTML += "<b>" + tr("Total debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nValue) + "<br>";
212                 strHTML += "<b>" + tr("Total credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nValue) + "<br>";
213             }
214
215             int64_t nTxFee = nDebit - wtx.GetValueOut();
216             if (nTxFee > 0)
217                 strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nTxFee) + "<br>";
218         }
219         else
220         {
221             //
222             // Mixed debit transaction
223             //
224             BOOST_FOREACH(const CTxIn& txin, wtx.vin)
225                 if (wallet->IsMine(txin))
226                     strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "<br>";
227             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
228                 if (wallet->IsMine(txout))
229                     strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "<br>";
230         }
231     }
232
233     strHTML += "<b>" + tr("Net amount") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nNet, true) + "<br>";
234
235     //
236     // Message
237     //
238     if (wtx.mapValue.count("message") && !wtx.mapValue["message"].empty())
239         strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "<br>";
240     if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty())
241         strHTML += "<br><b>" + tr("Comment") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
242
243     strHTML += "<b>" + tr("Transaction ID") + ":</b> " + TransactionRecord::formatSubTxId(wtx.GetHash(), rec->idx) + "<br>";
244
245     // Message from normal bitcoin:URI (bitcoin:123...?message=example)
246     foreach (const PAIRTYPE(string, string)& r, wtx.vOrderForm)
247         if (r.first == "Message")
248             strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(r.second, true) + "<br>";
249
250     //
251     // PaymentRequest info:
252     //
253     foreach (const PAIRTYPE(string, string)& r, wtx.vOrderForm)
254     {
255         if (r.first == "PaymentRequest")
256         {
257             PaymentRequestPlus req;
258             req.parse(QByteArray::fromRawData(r.second.data(), r.second.size()));
259             QString merchant;
260             if (req.getMerchant(PaymentServer::getCertStore(), merchant))
261                 strHTML += "<b>" + tr("Merchant") + ":</b> " + GUIUtil::HtmlEscape(merchant) + "<br>";
262         }
263     }
264
265     if (wtx.IsCoinBase())
266     {
267         quint32 numBlocksToMaturity = COINBASE_MATURITY +  1;
268         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>";
269     }
270
271     //
272     // Debug view
273     //
274     if (fDebug)
275     {
276         strHTML += "<hr><br>" + tr("Debug information") + "<br><br>";
277         BOOST_FOREACH(const CTxIn& txin, wtx.vin)
278             if(wallet->IsMine(txin))
279                 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "<br>";
280         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
281             if(wallet->IsMine(txout))
282                 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "<br>";
283
284         strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
285         strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
286
287         strHTML += "<br><b>" + tr("Inputs") + ":</b>";
288         strHTML += "<ul>";
289
290         BOOST_FOREACH(const CTxIn& txin, wtx.vin)
291         {
292             COutPoint prevout = txin.prevout;
293
294             CCoins prev;
295             if(pcoinsTip->GetCoins(prevout.hash, prev))
296             {
297                 if (prevout.n < prev.vout.size())
298                 {
299                     strHTML += "<li>";
300                     const CTxOut &vout = prev.vout[prevout.n];
301                     CTxDestination address;
302                     if (ExtractDestination(vout.scriptPubKey, address))
303                     {
304                         if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
305                             strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
306                         strHTML += QString::fromStdString(CBitcoinAddress(address).ToString());
307                     }
308                     strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatHtmlWithUnit(unit, vout.nValue);
309                     strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) & ISMINE_SPENDABLE ? tr("true") : tr("false")) + "</li>";
310                     strHTML = strHTML + " IsWatchOnly=" + (wallet->IsMine(vout) & ISMINE_WATCH_ONLY ? tr("true") : tr("false")) + "</li>";
311                 }
312             }
313         }
314
315         strHTML += "</ul>";
316     }
317
318     strHTML += "</font></html>";
319     return strHTML;
320 }
This page took 0.042989 seconds and 4 git commands to generate.