Master Core  v0.0.9 - 49a5c0d97abf09ef2911ddfe8d9551df59f9efd3-dirty
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
transactiondesc.cpp
Go to the documentation of this file.
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 "transactionrecord.h"
15 #include "ui_interface.h"
16 #include "wallet.h"
17 
18 #include <stdint.h>
19 #include <string>
20 
22 {
24  if (!IsFinalTx(wtx, chainActive.Height() + 1))
25  {
26  if (wtx.nLockTime < LOCKTIME_THRESHOLD)
27  return tr("Open for %n more block(s)", "", wtx.nLockTime - chainActive.Height());
28  else
29  return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime));
30  }
31  else
32  {
33  int nDepth = wtx.GetDepthInMainChain();
34  if (nDepth < 0)
35  return tr("conflicted");
36  else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
37  return tr("%1/offline").arg(nDepth);
38  else if (nDepth < 6)
39  return tr("%1/unconfirmed").arg(nDepth);
40  else
41  return tr("%1 confirmations").arg(nDepth);
42  }
43 }
44 
45 QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, int vout, int unit)
46 {
47  QString strHTML;
48 
49  LOCK2(cs_main, wallet->cs_wallet);
50  strHTML.reserve(4000);
51  strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
52 
53  int64_t nTime = wtx.GetTxTime();
54  int64_t nCredit = wtx.GetCredit();
55  int64_t nDebit = wtx.GetDebit();
56  int64_t nNet = nCredit - nDebit;
57 
58  strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx);
59  int nRequests = wtx.GetRequestCount();
60  if (nRequests != -1)
61  {
62  if (nRequests == 0)
63  strHTML += tr(", has not been successfully broadcast yet");
64  else if (nRequests > 0)
65  strHTML += tr(", broadcast through %n node(s)", "", nRequests);
66  }
67  strHTML += "<br>";
68 
69  strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>";
70 
71  //
72  // From
73  //
74  if (wtx.IsCoinBase())
75  {
76  strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>";
77  }
78  else if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty())
79  {
80  // Online transaction
81  strHTML += "<b>" + tr("From") + ":</b> " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>";
82  }
83  else
84  {
85  // Offline transaction
86  if (nNet > 0)
87  {
88  // Credit
89  BOOST_FOREACH(const CTxOut& txout, wtx.vout)
90  {
91  if (wallet->IsMine(txout))
92  {
93  CTxDestination address;
94  if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
95  {
96  if (wallet->mapAddressBook.count(address))
97  {
98  strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>";
99  strHTML += "<b>" + tr("To") + ":</b> ";
100  strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
101  if (!wallet->mapAddressBook[address].name.empty())
102  strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")";
103  else
104  strHTML += " (" + tr("own address") + ")";
105  strHTML += "<br>";
106  }
107  }
108  break;
109  }
110  }
111  }
112  }
113 
114  //
115  // To
116  //
117  if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty())
118  {
119  // Online transaction
120  std::string strAddress = wtx.mapValue["to"];
121  strHTML += "<b>" + tr("To") + ":</b> ";
122  CTxDestination dest = CBitcoinAddress(strAddress).Get();
123  if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].name.empty())
124  strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest].name) + " ";
125  strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
126  }
127 
128  //
129  // Amount
130  //
131  if (wtx.IsCoinBase() && nCredit == 0)
132  {
133  //
134  // Coinbase
135  //
136  int64_t nUnmatured = 0;
137  BOOST_FOREACH(const CTxOut& txout, wtx.vout)
138  nUnmatured += wallet->GetCredit(txout);
139  strHTML += "<b>" + tr("Credit") + ":</b> ";
140  if (wtx.IsInMainChain())
141  strHTML += BitcoinUnits::formatWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
142  else
143  strHTML += "(" + tr("not accepted") + ")";
144  strHTML += "<br>";
145  }
146  else if (nNet > 0)
147  {
148  //
149  // Credit
150  //
151  strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, nNet) + "<br>";
152  }
153  else
154  {
155  bool fAllFromMe = true;
156  BOOST_FOREACH(const CTxIn& txin, wtx.vin)
157  fAllFromMe = fAllFromMe && wallet->IsMine(txin);
158 
159  bool fAllToMe = true;
160  BOOST_FOREACH(const CTxOut& txout, wtx.vout)
161  fAllToMe = fAllToMe && wallet->IsMine(txout);
162 
163  if (fAllFromMe)
164  {
165  //
166  // Debit
167  //
168  BOOST_FOREACH(const CTxOut& txout, wtx.vout)
169  {
170  if (wallet->IsMine(txout))
171  continue;
172 
173  if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty())
174  {
175  // Offline transaction
176  CTxDestination address;
177  if (ExtractDestination(txout.scriptPubKey, address))
178  {
179  strHTML += "<b>" + tr("To") + ":</b> ";
180  if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
181  strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
182  strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
183  strHTML += "<br>";
184  }
185  }
186 
187  strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -txout.nValue) + "<br>";
188  }
189 
190  if (fAllToMe)
191  {
192  // Payment to self
193  int64_t nChange = wtx.GetChange();
194  int64_t nValue = nCredit - nChange;
195  strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -nValue) + "<br>";
196  strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, nValue) + "<br>";
197  }
198 
199  int64_t nTxFee = nDebit - wtx.GetValueOut();
200  if (nTxFee > 0)
201  strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -nTxFee) + "<br>";
202  }
203  else
204  {
205  //
206  // Mixed debit transaction
207  //
208  BOOST_FOREACH(const CTxIn& txin, wtx.vin)
209  if (wallet->IsMine(txin))
210  strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin)) + "<br>";
211  BOOST_FOREACH(const CTxOut& txout, wtx.vout)
212  if (wallet->IsMine(txout))
213  strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout)) + "<br>";
214  }
215  }
216 
217  strHTML += "<b>" + tr("Net amount") + ":</b> " + BitcoinUnits::formatWithUnit(unit, nNet, true) + "<br>";
218 
219  //
220  // Message
221  //
222  if (wtx.mapValue.count("message") && !wtx.mapValue["message"].empty())
223  strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "<br>";
224  if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty())
225  strHTML += "<br><b>" + tr("Comment") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
226 
227  strHTML += "<b>" + tr("Transaction ID") + ":</b> " + TransactionRecord::formatSubTxId(wtx.GetHash(), vout) + "<br>";
228 
229  // Message from normal bitcoin:URI (bitcoin:123...?message=example)
230  foreach (const PAIRTYPE(string, string)& r, wtx.vOrderForm)
231  if (r.first == "Message")
232  strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(r.second, true) + "<br>";
233 
234  //
235  // PaymentRequest info:
236  //
237  foreach (const PAIRTYPE(string, string)& r, wtx.vOrderForm)
238  {
239  if (r.first == "PaymentRequest")
240  {
241  PaymentRequestPlus req;
242  req.parse(QByteArray::fromRawData(r.second.data(), r.second.size()));
243  QString merchant;
244  if (req.getMerchant(PaymentServer::getCertStore(), merchant))
245  strHTML += "<b>" + tr("Merchant") + ":</b> " + GUIUtil::HtmlEscape(merchant) + "<br>";
246  }
247  }
248 
249  if (wtx.IsCoinBase())
250  {
251  quint32 numBlocksToMaturity = COINBASE_MATURITY + 1;
252  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>";
253  }
254 
255  //
256  // Debug view
257  //
258  if (fDebug)
259  {
260  strHTML += "<hr><br>" + tr("Debug information") + "<br><br>";
261  BOOST_FOREACH(const CTxIn& txin, wtx.vin)
262  if(wallet->IsMine(txin))
263  strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin)) + "<br>";
264  BOOST_FOREACH(const CTxOut& txout, wtx.vout)
265  if(wallet->IsMine(txout))
266  strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout)) + "<br>";
267 
268  strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
269  strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
270 
271  strHTML += "<br><b>" + tr("Inputs") + ":</b>";
272  strHTML += "<ul>";
273 
274  BOOST_FOREACH(const CTxIn& txin, wtx.vin)
275  {
276  COutPoint prevout = txin.prevout;
277 
278  CCoins prev;
279  if(pcoinsTip->GetCoins(prevout.hash, prev))
280  {
281  if (prevout.n < prev.vout.size())
282  {
283  strHTML += "<li>";
284  const CTxOut &vout = prev.vout[prevout.n];
285  CTxDestination address;
286  if (ExtractDestination(vout.scriptPubKey, address))
287  {
288  if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
289  strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
290  strHTML += QString::fromStdString(CBitcoinAddress(address).ToString());
291  }
292  strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(unit, vout.nValue);
293  strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? tr("true") : tr("false")) + "</li>";
294  }
295  }
296  }
297 
298  strHTML += "</ul>";
299  }
300 
301  strHTML += "</font></html>";
302  return strHTML;
303 }
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
Definition: main.cpp:594
int64_t GetValueOut() const
Definition: core.cpp:109
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule) ...
Definition: main.h:58
bool IsMine(const CTxIn &txin) const
Definition: wallet.cpp:653
static QString formatWithUnit(int unit, qint64 amount, bool plussign=false)
Format as string (with unit)
CScript scriptPubKey
Definition: core.h:123
int64_t GetChange() const
Definition: wallet.h:649
std::vector< CTxOut > vout
Definition: coins.h:75
bool fDebug
Definition: util.cpp:91
int64_t GetCredit(const CTxOut &txout) const
Definition: wallet.h:285
std::map< CTxDestination, CAddressBookData > mapAddressBook
Definition: wallet.h:173
#define PAIRTYPE(t1, t2)
Definition: util.h:48
CCriticalSection cs_wallet
Main wallet lock.
Definition: wallet.h:132
bool getMerchant(X509_STORE *certStore, QString &merchant) const
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:73
CCriticalSection cs_main
Definition: main.cpp:43
int64_t GetDebit() const
Definition: wallet.h:579
uint256 GetHash() const
Definition: core.cpp:75
QString HtmlEscape(const QString &str, bool fMultiLine)
Definition: guiutil.cpp:222
base58-encoded Bitcoin addresses.
Definition: base58.h:101
pruned version of CTransaction: only retains metadata and unspent transaction outputs ...
Definition: coins.h:68
unsigned int n
Definition: core.h:26
CTxDestination Get() const
Definition: base58.cpp:222
CChain chainActive
The currently-connected chain of blocks.
Definition: main.cpp:48
bool GetCoins(const uint256 &txid, CCoins &coins)
Definition: coins.cpp:74
mapValue_t mapValue
Definition: wallet.h:457
static X509_STORE * getCertStore()
Definition: paymentserver.h:82
#define AssertLockHeld(cs)
Definition: sync.h:97
int GetBlocksToMaturity() const
Definition: main.cpp:1033
#define LOCK2(cs1, cs2)
Definition: sync.h:157
int GetRequestCount() const
Definition: wallet.cpp:711
int Height() const
Return the maximal height in the chain.
Definition: main.h:1043
bool IsInMainChain() const
Definition: main.h:476
int64_t GetAdjustedTime()
Definition: util.cpp:1236
unsigned int nLockTime
Definition: core.h:192
An input of a transaction.
Definition: core.h:70
std::vector< CTxOut > vout
Definition: core.h:191
static QString formatSubTxId(const uint256 &hash, int vout)
Format subtransaction id.
std::vector< CTxIn > vin
Definition: core.h:190
An output of a transaction.
Definition: core.h:119
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: core.h:22
CCoinsViewCache * pcoinsTip
Global variable that points to the active CCoinsView (protected by cs_main)
Definition: main.cpp:413
int64_t GetDebit(const CTxIn &txin) const
Definition: wallet.cpp:669
bool parse(const QByteArray &data)
std::string ToString() const
Definition: core.cpp:140
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:451
int64_t GetTxTime() const
Definition: wallet.cpp:705
static const unsigned int LOCKTIME_THRESHOLD
Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timest...
Definition: main.h:60
bool IsMine(const CKeyStore &keystore, const CTxDestination &dest)
Definition: script.cpp:1448
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Definition: script.cpp:1493
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
Definition: wallet.h:100
int GetDepthInMainChain(CBlockIndex *&pindexRet) const
Definition: main.cpp:1023
bool IsCoinBase() const
Definition: core.h:232
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: script.h:218
static QString FormatTxStatus(const CWalletTx &wtx)
unsigned int nTimeReceived
Definition: wallet.h:460
COutPoint prevout
Definition: core.h:73
int64_t GetCredit(bool fUseCache=true) const
Definition: wallet.h:590
static QString toHTML(CWallet *wallet, CWalletTx &wtx, int vout, int unit)
int64_t nValue
Definition: core.h:122
std::vector< std::pair< std::string, std::string > > vOrderForm
Definition: wallet.h:458
uint256 hash
Definition: core.h:25