Line data Source code
1 : // Copyright (c) 2011-2014 The Bitcoin Core developers
2 : // Distributed under the MIT software license, see the accompanying
3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 :
5 : #include "transactionrecord.h"
6 :
7 : #include "base58.h"
8 : #include "consensus/consensus.h"
9 : #include "main.h"
10 : #include "timedata.h"
11 : #include "wallet/wallet.h"
12 :
13 : #include <stdint.h>
14 :
15 : #include <boost/foreach.hpp>
16 :
17 : /* Return positive answer if transaction should be shown in list.
18 : */
19 0 : bool TransactionRecord::showTransaction(const CWalletTx &wtx)
20 : {
21 0 : if (wtx.IsCoinBase())
22 : {
23 : // Ensures we show generated coins / mined transactions at depth 1
24 0 : if (!wtx.IsInMainChain())
25 : {
26 : return false;
27 : }
28 : }
29 : return true;
30 : }
31 :
32 : /*
33 : * Decompose CWallet transaction to model transaction records.
34 : */
35 0 : QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
36 : {
37 : QList<TransactionRecord> parts;
38 0 : int64_t nTime = wtx.GetTxTime();
39 0 : CAmount nCredit = wtx.GetCredit(ISMINE_ALL);
40 0 : CAmount nDebit = wtx.GetDebit(ISMINE_ALL);
41 0 : CAmount nNet = nCredit - nDebit;
42 0 : uint256 hash = wtx.GetHash();
43 0 : std::map<std::string, std::string> mapValue = wtx.mapValue;
44 :
45 0 : if (nNet > 0 || wtx.IsCoinBase())
46 : {
47 : //
48 : // Credit
49 : //
50 0 : BOOST_FOREACH(const CTxOut& txout, wtx.vout)
51 : {
52 0 : isminetype mine = wallet->IsMine(txout);
53 0 : if(mine)
54 : {
55 0 : TransactionRecord sub(hash, nTime);
56 : CTxDestination address;
57 0 : sub.idx = parts.size(); // sequence number
58 0 : sub.credit = txout.nValue;
59 0 : sub.involvesWatchAddress = mine & ISMINE_WATCH_ONLY;
60 0 : if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
61 : {
62 : // Received by Bitcoin Address
63 0 : sub.type = TransactionRecord::RecvWithAddress;
64 0 : sub.address = CBitcoinAddress(address).ToString();
65 : }
66 : else
67 : {
68 : // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction
69 0 : sub.type = TransactionRecord::RecvFromOther;
70 0 : sub.address = mapValue["from"];
71 : }
72 0 : if (wtx.IsCoinBase())
73 : {
74 : // Generated
75 0 : sub.type = TransactionRecord::Generated;
76 : }
77 :
78 0 : parts.append(sub);
79 : }
80 : }
81 : }
82 : else
83 : {
84 0 : bool involvesWatchAddress = false;
85 0 : isminetype fAllFromMe = ISMINE_SPENDABLE;
86 0 : BOOST_FOREACH(const CTxIn& txin, wtx.vin)
87 : {
88 0 : isminetype mine = wallet->IsMine(txin);
89 0 : if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true;
90 0 : if(fAllFromMe > mine) fAllFromMe = mine;
91 : }
92 :
93 0 : isminetype fAllToMe = ISMINE_SPENDABLE;
94 0 : BOOST_FOREACH(const CTxOut& txout, wtx.vout)
95 : {
96 0 : isminetype mine = wallet->IsMine(txout);
97 0 : if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true;
98 0 : if(fAllToMe > mine) fAllToMe = mine;
99 : }
100 :
101 0 : if (fAllFromMe && fAllToMe)
102 : {
103 : // Payment to self
104 0 : CAmount nChange = wtx.GetChange();
105 :
106 : parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "",
107 0 : -(nDebit - nChange), nCredit - nChange));
108 0 : parts.last().involvesWatchAddress = involvesWatchAddress; // maybe pass to TransactionRecord as constructor argument
109 : }
110 0 : else if (fAllFromMe)
111 : {
112 : //
113 : // Debit
114 : //
115 0 : CAmount nTxFee = nDebit - wtx.GetValueOut();
116 :
117 0 : for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
118 : {
119 0 : const CTxOut& txout = wtx.vout[nOut];
120 0 : TransactionRecord sub(hash, nTime);
121 0 : sub.idx = parts.size();
122 0 : sub.involvesWatchAddress = involvesWatchAddress;
123 :
124 0 : if(wallet->IsMine(txout))
125 : {
126 : // Ignore parts sent to self, as this is usually the change
127 : // from a transaction sent back to our own address.
128 0 : continue;
129 : }
130 :
131 : CTxDestination address;
132 0 : if (ExtractDestination(txout.scriptPubKey, address))
133 : {
134 : // Sent to Bitcoin Address
135 0 : sub.type = TransactionRecord::SendToAddress;
136 0 : sub.address = CBitcoinAddress(address).ToString();
137 : }
138 : else
139 : {
140 : // Sent to IP, or other non-address transaction like OP_EVAL
141 0 : sub.type = TransactionRecord::SendToOther;
142 0 : sub.address = mapValue["to"];
143 : }
144 :
145 0 : CAmount nValue = txout.nValue;
146 : /* Add fee to first output */
147 0 : if (nTxFee > 0)
148 : {
149 0 : nValue += nTxFee;
150 0 : nTxFee = 0;
151 : }
152 0 : sub.debit = -nValue;
153 :
154 0 : parts.append(sub);
155 0 : }
156 : }
157 : else
158 : {
159 : //
160 : // Mixed debit transaction, can't break down payees
161 : //
162 0 : parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0));
163 0 : parts.last().involvesWatchAddress = involvesWatchAddress;
164 : }
165 : }
166 :
167 0 : return parts;
168 : }
169 :
170 0 : void TransactionRecord::updateStatus(const CWalletTx &wtx)
171 : {
172 0 : AssertLockHeld(cs_main);
173 : // Determine transaction status
174 :
175 : // Find the block the tx is in
176 0 : CBlockIndex* pindex = NULL;
177 0 : BlockMap::iterator mi = mapBlockIndex.find(wtx.hashBlock);
178 0 : if (mi != mapBlockIndex.end())
179 0 : pindex = (*mi).second;
180 :
181 : // Sort order, unrecorded transactions sort to the top
182 0 : status.sortKey = strprintf("%010d-%01d-%010u-%03d",
183 : (pindex ? pindex->nHeight : std::numeric_limits<int>::max()),
184 0 : (wtx.IsCoinBase() ? 1 : 0),
185 : wtx.nTimeReceived,
186 : idx);
187 0 : status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0);
188 0 : status.depth = wtx.GetDepthInMainChain();
189 0 : status.cur_num_blocks = chainActive.Height();
190 :
191 0 : if (!CheckFinalTx(wtx))
192 : {
193 0 : if (wtx.nLockTime < LOCKTIME_THRESHOLD)
194 : {
195 0 : status.status = TransactionStatus::OpenUntilBlock;
196 0 : status.open_for = wtx.nLockTime - chainActive.Height();
197 : }
198 : else
199 : {
200 0 : status.status = TransactionStatus::OpenUntilDate;
201 0 : status.open_for = wtx.nLockTime;
202 : }
203 : }
204 : // For generated transactions, determine maturity
205 0 : else if(type == TransactionRecord::Generated)
206 : {
207 0 : if (wtx.GetBlocksToMaturity() > 0)
208 : {
209 0 : status.status = TransactionStatus::Immature;
210 :
211 0 : if (wtx.IsInMainChain())
212 : {
213 0 : status.matures_in = wtx.GetBlocksToMaturity();
214 :
215 : // Check if the block was requested by anyone
216 0 : if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
217 0 : status.status = TransactionStatus::MaturesWarning;
218 : }
219 : else
220 : {
221 0 : status.status = TransactionStatus::NotAccepted;
222 : }
223 : }
224 : else
225 : {
226 0 : status.status = TransactionStatus::Confirmed;
227 : }
228 : }
229 : else
230 : {
231 0 : if (status.depth < 0)
232 : {
233 0 : status.status = TransactionStatus::Conflicted;
234 : }
235 0 : else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
236 : {
237 0 : status.status = TransactionStatus::Offline;
238 : }
239 0 : else if (status.depth == 0)
240 : {
241 0 : status.status = TransactionStatus::Unconfirmed;
242 : }
243 0 : else if (status.depth < RecommendedNumConfirmations)
244 : {
245 0 : status.status = TransactionStatus::Confirming;
246 : }
247 : else
248 : {
249 0 : status.status = TransactionStatus::Confirmed;
250 : }
251 : }
252 :
253 0 : }
254 :
255 0 : bool TransactionRecord::statusUpdateNeeded()
256 : {
257 0 : AssertLockHeld(cs_main);
258 0 : return status.cur_num_blocks != chainActive.Height();
259 : }
260 :
261 0 : QString TransactionRecord::getTxID() const
262 : {
263 0 : return formatSubTxId(hash, idx);
264 : }
265 :
266 0 : QString TransactionRecord::formatSubTxId(const uint256 &hash, int vout)
267 : {
268 0 : return QString::fromStdString(hash.ToString() + strprintf("-%03d", vout));
269 0 : }
270 :
|