You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

transactionrecord.cpp 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // Copyright (c) 2011-2013 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. #include "transactionrecord.h"
  5. #include "base58.h"
  6. #include "wallet.h"
  7. #include <stdint.h>
  8. /* Return positive answer if transaction should be shown in list.
  9. */
  10. bool TransactionRecord::showTransaction(const CWalletTx &wtx)
  11. {
  12. if (wtx.IsCoinBase())
  13. {
  14. // Ensures we show generated coins / mined transactions at depth 1
  15. if (!wtx.IsInMainChain())
  16. {
  17. return false;
  18. }
  19. }
  20. return true;
  21. }
  22. /*
  23. * Decompose CWallet transaction to model transaction records.
  24. */
  25. QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
  26. {
  27. QList<TransactionRecord> parts;
  28. int64_t nTime = wtx.GetTxTime();
  29. int64_t nCredit = wtx.GetCredit(true);
  30. int64_t nDebit = wtx.GetDebit();
  31. int64_t nNet = nCredit - nDebit;
  32. uint256 hash = wtx.GetHash();
  33. std::map<std::string, std::string> mapValue = wtx.mapValue;
  34. if (nNet > 0 || wtx.IsCoinBase())
  35. {
  36. //
  37. // Credit
  38. //
  39. BOOST_FOREACH(const CTxOut& txout, wtx.vout)
  40. {
  41. if(wallet->IsMine(txout))
  42. {
  43. TransactionRecord sub(hash, nTime);
  44. CTxDestination address;
  45. sub.idx = parts.size(); // sequence number
  46. sub.credit = txout.nValue;
  47. if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
  48. {
  49. // Received by Bitcoin Address
  50. sub.type = TransactionRecord::RecvWithAddress;
  51. sub.address = CBitcoinAddress(address).ToString();
  52. }
  53. else
  54. {
  55. // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction
  56. sub.type = TransactionRecord::RecvFromOther;
  57. sub.address = mapValue["from"];
  58. }
  59. if (wtx.IsCoinBase())
  60. {
  61. // Generated
  62. sub.type = TransactionRecord::Generated;
  63. }
  64. parts.append(sub);
  65. }
  66. }
  67. }
  68. else
  69. {
  70. bool fAllFromMe = true;
  71. BOOST_FOREACH(const CTxIn& txin, wtx.vin)
  72. fAllFromMe = fAllFromMe && wallet->IsMine(txin);
  73. bool fAllToMe = true;
  74. BOOST_FOREACH(const CTxOut& txout, wtx.vout)
  75. fAllToMe = fAllToMe && wallet->IsMine(txout);
  76. if (fAllFromMe && fAllToMe)
  77. {
  78. // Payment to self
  79. int64_t nChange = wtx.GetChange();
  80. parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "",
  81. -(nDebit - nChange), nCredit - nChange));
  82. }
  83. else if (fAllFromMe)
  84. {
  85. //
  86. // Debit
  87. //
  88. int64_t nTxFee = nDebit - wtx.GetValueOut();
  89. for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
  90. {
  91. const CTxOut& txout = wtx.vout[nOut];
  92. TransactionRecord sub(hash, nTime);
  93. sub.idx = parts.size();
  94. if(wallet->IsMine(txout))
  95. {
  96. // Ignore parts sent to self, as this is usually the change
  97. // from a transaction sent back to our own address.
  98. continue;
  99. }
  100. CTxDestination address;
  101. if (ExtractDestination(txout.scriptPubKey, address))
  102. {
  103. // Sent to Bitcoin Address
  104. sub.type = TransactionRecord::SendToAddress;
  105. sub.address = CBitcoinAddress(address).ToString();
  106. }
  107. else
  108. {
  109. // Sent to IP, or other non-address transaction like OP_EVAL
  110. sub.type = TransactionRecord::SendToOther;
  111. sub.address = mapValue["to"];
  112. }
  113. int64_t nValue = txout.nValue;
  114. /* Add fee to first output */
  115. if (nTxFee > 0)
  116. {
  117. nValue += nTxFee;
  118. nTxFee = 0;
  119. }
  120. sub.debit = -nValue;
  121. parts.append(sub);
  122. }
  123. }
  124. else
  125. {
  126. //
  127. // Mixed debit transaction, can't break down payees
  128. //
  129. parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0));
  130. }
  131. }
  132. return parts;
  133. }
  134. void TransactionRecord::updateStatus(const CWalletTx &wtx)
  135. {
  136. // Determine transaction status
  137. // Find the block the tx is in
  138. CBlockIndex* pindex = NULL;
  139. std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(wtx.hashBlock);
  140. if (mi != mapBlockIndex.end())
  141. pindex = (*mi).second;
  142. // Sort order, unrecorded transactions sort to the top
  143. status.sortKey = strprintf("%010d-%01d-%010u-%03d",
  144. (pindex ? pindex->nHeight : std::numeric_limits<int>::max()),
  145. (wtx.IsCoinBase() ? 1 : 0),
  146. wtx.nTimeReceived,
  147. idx);
  148. status.confirmed = wtx.IsConfirmed();
  149. status.depth = wtx.GetDepthInMainChain();
  150. status.cur_num_blocks = chainActive.Height();
  151. if (!IsFinalTx(wtx, chainActive.Height() + 1))
  152. {
  153. if (wtx.nLockTime < LOCKTIME_THRESHOLD)
  154. {
  155. status.status = TransactionStatus::OpenUntilBlock;
  156. status.open_for = wtx.nLockTime - chainActive.Height();
  157. }
  158. else
  159. {
  160. status.status = TransactionStatus::OpenUntilDate;
  161. status.open_for = wtx.nLockTime;
  162. }
  163. }
  164. else
  165. {
  166. if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
  167. {
  168. status.status = TransactionStatus::Offline;
  169. }
  170. else if (status.depth < NumConfirmations)
  171. {
  172. status.status = TransactionStatus::Unconfirmed;
  173. }
  174. else
  175. {
  176. status.status = TransactionStatus::HaveConfirmations;
  177. }
  178. }
  179. // For generated transactions, determine maturity
  180. if(type == TransactionRecord::Generated)
  181. {
  182. int64_t nCredit = wtx.GetCredit(true);
  183. if (nCredit == 0)
  184. {
  185. status.maturity = TransactionStatus::Immature;
  186. if (wtx.IsInMainChain())
  187. {
  188. status.matures_in = wtx.GetBlocksToMaturity();
  189. // Check if the block was requested by anyone
  190. if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
  191. status.maturity = TransactionStatus::MaturesWarning;
  192. }
  193. else
  194. {
  195. status.maturity = TransactionStatus::NotAccepted;
  196. }
  197. }
  198. else
  199. {
  200. status.maturity = TransactionStatus::Mature;
  201. }
  202. }
  203. }
  204. bool TransactionRecord::statusUpdateNeeded()
  205. {
  206. return status.cur_num_blocks != chainActive.Height();
  207. }
  208. QString TransactionRecord::getTxID() const
  209. {
  210. return formatSubTxId(hash, idx);
  211. }
  212. QString TransactionRecord::formatSubTxId(const uint256 &hash, int vout)
  213. {
  214. return QString::fromStdString(hash.ToString() + strprintf("-%03d", vout));
  215. }