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