Anoncoin  0.9.4
P2P Digital Currency
transactiondesc.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2014 The Bitcoin developers
2 // Copyright (c) 2013-2014 The Anoncoin Core developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include "transactiondesc.h"
7 
8 #include "anoncoinunits.h"
9 #include "guiutil.h"
10 
11 #include "base58.h"
12 #include "db.h"
13 #include "main.h"
14 #include "paymentserver.h"
15 #include "transactionrecord.h"
16 #include "ui_interface.h"
17 #include "wallet.h"
18 #include "script.h"
19 
20 #include <stdint.h>
21 #include <string>
22 
24 {
26  if (!IsFinalTx(wtx, chainActive.Height() + 1))
27  {
28  if (wtx.nLockTime < LOCKTIME_THRESHOLD)
29  return tr("Open for %n more block(s)", "", wtx.nLockTime - chainActive.Height());
30  else
31  return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime));
32  }
33  else
34  {
35  int nDepth = wtx.GetDepthInMainChain();
36  if (nDepth < 0)
37  return tr("conflicted");
38  else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
39  return tr("%1/offline").arg(nDepth);
40  else if (nDepth < 6)
41  return tr("%1/unconfirmed").arg(nDepth);
42  else
43  return tr("%1 confirmations").arg(nDepth);
44  }
45 }
46 
47 QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionRecord *rec, int unit)
48 {
49  QString strHTML;
50 
51  LOCK2(cs_main, wallet->cs_wallet);
52  strHTML.reserve(4000);
53  strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
54 
55  int64_t nTime = wtx.GetTxTime();
56  int64_t nCredit = wtx.GetCredit(ISMINE_ALL);
57  int64_t nDebit = wtx.GetDebit(ISMINE_ALL);
58  int64_t nNet = nCredit - nDebit;
59 
60  strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx);
61  int nRequests = wtx.GetRequestCount();
62  if (nRequests != -1)
63  {
64  if (nRequests == 0)
65  strHTML += tr(", has not been successfully broadcast yet");
66  else if (nRequests > 0)
67  strHTML += tr(", broadcast through %n node(s)", "", nRequests);
68  }
69  strHTML += "<br>";
70 
71  strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>";
72 
73  //
74  // From
75  //
76  if (wtx.IsCoinBase())
77  {
78  strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>";
79  }
80  else if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty())
81  {
82  // Online transaction
83  strHTML += "<b>" + tr("From") + ":</b> " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>";
84  }
85  else
86  {
87  // Offline transaction
88  if (nNet > 0)
89  {
90  // Credit
91  if (CAnoncoinAddress(rec->address).IsValid())
92  {
93  CTxDestination address = CAnoncoinAddress(rec->address).Get();
94  if (wallet->mapAddressBook.count(address))
95  {
96  strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>";
97  strHTML += "<b>" + tr("To") + ":</b> ";
98  strHTML += GUIUtil::HtmlEscape(rec->address);
99  QString addressOwned = (::IsMine(*wallet, address) == ISMINE_SPENDABLE) ? tr("own address") : tr("watch-only");
100  if (!wallet->mapAddressBook[address].name.empty())
101  strHTML += " (" + addressOwned + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")";
102  else
103  strHTML += " (" + addressOwned + ")";
104  strHTML += "<br>";
105  }
106  }
107  }
108  }
109 
110  //
111  // To
112  //
113  if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty())
114  {
115  // Online transaction
116  std::string strAddress = wtx.mapValue["to"];
117  strHTML += "<b>" + tr("To") + ":</b> ";
118  CTxDestination dest = CAnoncoinAddress(strAddress).Get();
119  if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].name.empty())
120  strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest].name) + " ";
121  strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
122  }
123 
124  //
125  // Amount
126  //
127  if (wtx.IsCoinBase() && nCredit == 0)
128  {
129  //
130  // Coinbase
131  //
132  int64_t nUnmatured = 0;
133  BOOST_FOREACH(const CTxOut& txout, wtx.vout)
134  nUnmatured += wallet->GetCredit(txout, ISMINE_ALL);
135  strHTML += "<b>" + tr("Credit") + ":</b> ";
136  if (wtx.IsInMainChain())
137  strHTML += AnoncoinUnits::formatWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
138  else
139  strHTML += "(" + tr("not accepted") + ")";
140  strHTML += "<br>";
141  }
142  else if (nNet > 0)
143  {
144  //
145  // Credit
146  //
147  strHTML += "<b>" + tr("Credit") + ":</b> " + AnoncoinUnits::formatWithUnit(unit, nNet) + "<br>";
148  }
149  else
150  {
151  isminetype fAllFromMe = ISMINE_SPENDABLE;
152  BOOST_FOREACH(const CTxIn& txin, wtx.vin)
153  {
154  isminetype mine = wallet->IsMine(txin);
155  if(fAllFromMe > mine) fAllFromMe = mine;
156  }
157 
158  isminetype fAllToMe = ISMINE_SPENDABLE;
159  BOOST_FOREACH(const CTxOut& txout, wtx.vout)
160  {
161  isminetype mine = wallet->IsMine(txout);
162  if(fAllToMe > mine) fAllToMe = mine;
163  }
164 
165  if (fAllFromMe)
166  {
167  if(fAllFromMe == ISMINE_WATCH_ONLY)
168  strHTML += "<b>" + tr("From") + ":</b> " + tr("watch-only") + "<br>";
169 
170  //
171  // Debit
172  //
173  BOOST_FOREACH(const CTxOut& txout, wtx.vout)
174  {
175  // Ignore change
176  isminetype toSelf = wallet->IsMine(txout);
177  if ((toSelf == ISMINE_SPENDABLE) && (fAllFromMe == ISMINE_SPENDABLE))
178  continue;
179 
180  if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty())
181  {
182  // Offline transaction
183  CTxDestination address;
184  if (ExtractDestination(txout.scriptPubKey, address))
185  {
186  strHTML += "<b>" + tr("To") + ":</b> ";
187  if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
188  strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
189  strHTML += GUIUtil::HtmlEscape(CAnoncoinAddress(address).ToString());
190  if(toSelf == ISMINE_SPENDABLE)
191  strHTML += " (own address)";
192  else if(toSelf == ISMINE_WATCH_ONLY)
193  strHTML += " (watch-only)";
194  strHTML += "<br>";
195  }
196  }
197 
198  strHTML += "<b>" + tr("Debit") + ":</b> " + AnoncoinUnits::formatWithUnit(unit, -txout.nValue) + "<br>";
199  if(toSelf)
200  strHTML += "<b>" + tr("Credit") + ":</b> " + AnoncoinUnits::formatWithUnit(unit, txout.nValue) + "<br>";
201  }
202 
203  if (fAllToMe)
204  {
205  // Payment to self
206  int64_t nChange = wtx.GetChange();
207  int64_t nValue = nCredit - nChange;
208  strHTML += "<b>" + tr("Total debit") + ":</b> " + AnoncoinUnits::formatWithUnit(unit, -nValue) + "<br>";
209  strHTML += "<b>" + tr("Total credit") + ":</b> " + AnoncoinUnits::formatWithUnit(unit, nValue) + "<br>";
210  }
211 
212  int64_t nTxFee = nDebit - wtx.GetValueOut();
213  if (nTxFee > 0)
214  strHTML += "<b>" + tr("Transaction fee") + ":</b> " + AnoncoinUnits::formatWithUnit(unit, -nTxFee) + "<br>";
215  }
216  else
217  {
218  //
219  // Mixed debit transaction
220  //
221  BOOST_FOREACH(const CTxIn& txin, wtx.vin)
222  if (wallet->IsMine(txin))
223  strHTML += "<b>" + tr("Debit") + ":</b> " + AnoncoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "<br>";
224  BOOST_FOREACH(const CTxOut& txout, wtx.vout)
225  if (wallet->IsMine(txout))
226  strHTML += "<b>" + tr("Credit") + ":</b> " + AnoncoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "<br>";
227  }
228  }
229 
230  strHTML += "<b>" + tr("Net amount") + ":</b> " + AnoncoinUnits::formatWithUnit(unit, nNet, true) + "<br>";
231 
232  //
233  // Message
234  //
235  if (wtx.mapValue.count("message") && !wtx.mapValue["message"].empty())
236  strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "<br>";
237  if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty())
238  strHTML += "<br><b>" + tr("Comment") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
239 
240  strHTML += "<b>" + tr("Transaction ID") + ":</b> " + TransactionRecord::formatSubTxId(wtx.GetHash(), rec->idx) + "<br>";
241 
242  // Message from normal anoncoin:URI (anoncoin:123...?message=example)
243  foreach (const PAIRTYPE(string, string)& r, wtx.vOrderForm)
244  if (r.first == "Message")
245  strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(r.second, true) + "<br>";
246 
247  //
248  // PaymentRequest info:
249  //
250  foreach (const PAIRTYPE(string, string)& r, wtx.vOrderForm)
251  {
252  if (r.first == "PaymentRequest")
253  {
254  PaymentRequestPlus req;
255  req.parse(QByteArray::fromRawData(r.second.data(), r.second.size()));
256  QString merchant;
257  if (req.getMerchant(PaymentServer::getCertStore(), merchant))
258  strHTML += "<b>" + tr("Merchant") + ":</b> " + GUIUtil::HtmlEscape(merchant) + "<br>";
259  }
260  }
261 
262  if (wtx.IsCoinBase())
263  {
264  quint32 numBlocksToMaturity = COINBASE_MATURITY + 1;
265  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>";
266  }
267 
268  //
269  // Debug view
270  //
271  if (fDebug)
272  {
273  strHTML += "<hr><br>" + tr("Debug information") + "<br><br>";
274  BOOST_FOREACH(const CTxIn& txin, wtx.vin)
275  if(wallet->IsMine(txin))
276  strHTML += "<b>" + tr("Debit") + ":</b> " + AnoncoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "<br>";
277  BOOST_FOREACH(const CTxOut& txout, wtx.vout)
278  if(wallet->IsMine(txout))
279  strHTML += "<b>" + tr("Credit") + ":</b> " + AnoncoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "<br>";
280 
281  strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
282  strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
283 
284  strHTML += "<br><b>" + tr("Inputs") + ":</b>";
285  strHTML += "<ul>";
286 
287  BOOST_FOREACH(const CTxIn& txin, wtx.vin)
288  {
289  COutPoint prevout = txin.prevout;
290 
291  CCoins prev;
292  if(pcoinsTip->GetCoins(prevout.hash, prev))
293  {
294  if (prevout.n < prev.vout.size())
295  {
296  strHTML += "<li>";
297  const CTxOut &vout = prev.vout[prevout.n];
298  CTxDestination address;
299  if (ExtractDestination(vout.scriptPubKey, address))
300  {
301  if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
302  strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
303  strHTML += QString::fromStdString(CAnoncoinAddress(address).ToString());
304  }
305  strHTML = strHTML + " " + tr("Amount") + "=" + AnoncoinUnits::formatWithUnit(unit, vout.nValue);
306  strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) & ISMINE_SPENDABLE ? tr("true") : tr("false")) + "</li>";
307  strHTML = strHTML + " IsWatchOnly=" + (wallet->IsMine(vout) & ISMINE_WATCH_ONLY ? tr("true") : tr("false")) + "</li>";
308  }
309  }
310  }
311 
312  strHTML += "</ul>";
313  }
314 
315  strHTML += "</font></html>";
316  return strHTML;
317 }
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
Definition: main.cpp:617
int64_t GetCredit(const CTxOut &txout, const isminefilter &filter) const
Definition: wallet.h:295
int64_t GetValueOut() const
Definition: core.cpp:110
isminetype IsMine(const CTxIn &txin) const
Definition: wallet.cpp:691
int idx
Subtransaction index, for sort key.
CScript scriptPubKey
Definition: core.h:125
int64_t GetChange() const
Definition: wallet.h:764
std::vector< CTxOut > vout
Definition: coins.h:76
bool fDebug
Definition: util.cpp:91
std::map< CTxDestination, CAddressBookData > mapAddressBook
Definition: wallet.h:174
#define PAIRTYPE(t1, t2)
Definition: util.h:49
CCriticalSection cs_wallet
Main wallet lock.
Definition: wallet.h:133
static QString formatWithUnit(int unit, qint64 amount, bool plussign=false)
Format as string (with unit)
isminetype IsMine(const CKeyStore &keystore, const CTxDestination &dest)
Definition: script.cpp:1450
bool getMerchant(X509_STORE *certStore, QString &merchant) const
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:75
CTxDestination Get() const
Definition: base58.cpp:223
CCriticalSection cs_main
Definition: main.cpp:38
uint256 GetHash() const
Definition: core.cpp:76
QString HtmlEscape(const QString &str, bool fMultiLine)
Definition: guiutil.cpp:228
pruned version of CTransaction: only retains metadata and unspent transaction outputs ...
Definition: coins.h:69
unsigned int n
Definition: core.h:28
CChain chainActive
The currently-connected chain of blocks.
Definition: main.cpp:43
bool IsValid() const
Definition: base58.cpp:216
bool GetCoins(const uint256 &txid, CCoins &coins)
Definition: coins.cpp:75
int64_t GetDebit(const CTxIn &txin, const isminefilter &filter) const
Definition: wallet.cpp:706
mapValue_t mapValue
Definition: wallet.h:470
isminetype
IsMine() return codes.
Definition: script.h:197
static X509_STORE * getCertStore()
Definition: paymentserver.h:83
#define AssertLockHeld(cs)
Definition: sync.h:98
int GetBlocksToMaturity() const
Definition: main.cpp:1059
#define LOCK2(cs1, cs2)
Definition: sync.h:158
int GetRequestCount() const
Definition: wallet.cpp:750
int Height() const
Return the maximal height in the chain.
Definition: main.h:1055
bool IsInMainChain() const
Definition: main.h:486
UI model for a transaction.
int64_t GetAdjustedTime()
Definition: util.cpp:1241
unsigned int nLockTime
Definition: core.h:188
An input of a transaction.
Definition: core.h:72
std::vector< CTxOut > vout
Definition: core.h:187
static QString formatSubTxId(const uint256 &hash, int vout)
Format subtransaction id.
std::vector< CTxIn > vin
Definition: core.h:186
base58-encoded Anoncoin addresses.
Definition: base58.h:102
An output of a transaction.
Definition: core.h:121
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: core.h:24
CCoinsViewCache * pcoinsTip
Global variable that points to the active CCoinsView (protected by cs_main)
Definition: main.cpp:436
bool parse(const QByteArray &data)
std::string ToString() const
Definition: core.cpp:141
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:464
int64_t GetTxTime() const
Definition: wallet.cpp:744
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: keystore.h:17
int64_t GetCredit(const isminefilter &filter) const
Definition: wallet.h:644
int64_t GetDebit(const isminefilter &filter) const
Definition: wallet.h:613
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Definition: script.cpp:1513
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
Definition: wallet.h:101
int GetDepthInMainChain(CBlockIndex *&pindexRet) const
Definition: main.cpp:1049
bool IsCoinBase() const
Definition: core.h:228
static QString FormatTxStatus(const CWalletTx &wtx)
unsigned int nTimeReceived
Definition: wallet.h:473
COutPoint prevout
Definition: core.h:75
static QString toHTML(CWallet *wallet, CWalletTx &wtx, TransactionRecord *rec, int unit)
int64_t nValue
Definition: core.h:124
std::vector< std::pair< std::string, std::string > > vOrderForm
Definition: wallet.h:471
uint256 hash
Definition: core.h:27