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