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.9KB

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