Support more than one CScheduler thread for serial clients
[bitcoinplatinum.git] / src / qt / transactionrecord.cpp
blobda070da084ba5fba66c6e6409144311242bcdc74
1 // Copyright (c) 2011-2016 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.
5 #include "transactionrecord.h"
7 #include "base58.h"
8 #include "consensus/consensus.h"
9 #include "validation.h"
10 #include "timedata.h"
11 #include "wallet/wallet.h"
13 #include <stdint.h>
15 #include <boost/foreach.hpp>
17 /* Return positive answer if transaction should be shown in list.
19 bool TransactionRecord::showTransaction(const CWalletTx &wtx)
21 // There are currently no cases where we hide transactions, but
22 // we may want to use this in the future for things like RBF.
23 return true;
27 * Decompose CWallet transaction to model transaction records.
29 QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
31 QList<TransactionRecord> parts;
32 int64_t nTime = wtx.GetTxTime();
33 CAmount nCredit = wtx.GetCredit(ISMINE_ALL);
34 CAmount nDebit = wtx.GetDebit(ISMINE_ALL);
35 CAmount nNet = nCredit - nDebit;
36 uint256 hash = wtx.GetHash();
37 std::map<std::string, std::string> mapValue = wtx.mapValue;
39 if (nNet > 0 || wtx.IsCoinBase())
42 // Credit
44 for(unsigned int i = 0; i < wtx.tx->vout.size(); i++)
46 const CTxOut& txout = wtx.tx->vout[i];
47 isminetype mine = wallet->IsMine(txout);
48 if(mine)
50 TransactionRecord sub(hash, nTime);
51 CTxDestination address;
52 sub.idx = i; // vout index
53 sub.credit = txout.nValue;
54 sub.involvesWatchAddress = mine & ISMINE_WATCH_ONLY;
55 if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
57 // Received by Bitcoin Address
58 sub.type = TransactionRecord::RecvWithAddress;
59 sub.address = CBitcoinAddress(address).ToString();
61 else
63 // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction
64 sub.type = TransactionRecord::RecvFromOther;
65 sub.address = mapValue["from"];
67 if (wtx.IsCoinBase())
69 // Generated
70 sub.type = TransactionRecord::Generated;
73 parts.append(sub);
77 else
79 bool involvesWatchAddress = false;
80 isminetype fAllFromMe = ISMINE_SPENDABLE;
81 for (const CTxIn& txin : wtx.tx->vin)
83 isminetype mine = wallet->IsMine(txin);
84 if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true;
85 if(fAllFromMe > mine) fAllFromMe = mine;
88 isminetype fAllToMe = ISMINE_SPENDABLE;
89 for (const CTxOut& txout : wtx.tx->vout)
91 isminetype mine = wallet->IsMine(txout);
92 if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true;
93 if(fAllToMe > mine) fAllToMe = mine;
96 if (fAllFromMe && fAllToMe)
98 // Payment to self
99 CAmount nChange = wtx.GetChange();
101 parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "",
102 -(nDebit - nChange), nCredit - nChange));
103 parts.last().involvesWatchAddress = involvesWatchAddress; // maybe pass to TransactionRecord as constructor argument
105 else if (fAllFromMe)
108 // Debit
110 CAmount nTxFee = nDebit - wtx.tx->GetValueOut();
112 for (unsigned int nOut = 0; nOut < wtx.tx->vout.size(); nOut++)
114 const CTxOut& txout = wtx.tx->vout[nOut];
115 TransactionRecord sub(hash, nTime);
116 sub.idx = nOut;
117 sub.involvesWatchAddress = involvesWatchAddress;
119 if(wallet->IsMine(txout))
121 // Ignore parts sent to self, as this is usually the change
122 // from a transaction sent back to our own address.
123 continue;
126 CTxDestination address;
127 if (ExtractDestination(txout.scriptPubKey, address))
129 // Sent to Bitcoin Address
130 sub.type = TransactionRecord::SendToAddress;
131 sub.address = CBitcoinAddress(address).ToString();
133 else
135 // Sent to IP, or other non-address transaction like OP_EVAL
136 sub.type = TransactionRecord::SendToOther;
137 sub.address = mapValue["to"];
140 CAmount nValue = txout.nValue;
141 /* Add fee to first output */
142 if (nTxFee > 0)
144 nValue += nTxFee;
145 nTxFee = 0;
147 sub.debit = -nValue;
149 parts.append(sub);
152 else
155 // Mixed debit transaction, can't break down payees
157 parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0));
158 parts.last().involvesWatchAddress = involvesWatchAddress;
162 return parts;
165 void TransactionRecord::updateStatus(const CWalletTx &wtx)
167 AssertLockHeld(cs_main);
168 // Determine transaction status
170 // Find the block the tx is in
171 CBlockIndex* pindex = NULL;
172 BlockMap::iterator mi = mapBlockIndex.find(wtx.hashBlock);
173 if (mi != mapBlockIndex.end())
174 pindex = (*mi).second;
176 // Sort order, unrecorded transactions sort to the top
177 status.sortKey = strprintf("%010d-%01d-%010u-%03d",
178 (pindex ? pindex->nHeight : std::numeric_limits<int>::max()),
179 (wtx.IsCoinBase() ? 1 : 0),
180 wtx.nTimeReceived,
181 idx);
182 status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0);
183 status.depth = wtx.GetDepthInMainChain();
184 status.cur_num_blocks = chainActive.Height();
186 if (!CheckFinalTx(wtx))
188 if (wtx.tx->nLockTime < LOCKTIME_THRESHOLD)
190 status.status = TransactionStatus::OpenUntilBlock;
191 status.open_for = wtx.tx->nLockTime - chainActive.Height();
193 else
195 status.status = TransactionStatus::OpenUntilDate;
196 status.open_for = wtx.tx->nLockTime;
199 // For generated transactions, determine maturity
200 else if(type == TransactionRecord::Generated)
202 if (wtx.GetBlocksToMaturity() > 0)
204 status.status = TransactionStatus::Immature;
206 if (wtx.IsInMainChain())
208 status.matures_in = wtx.GetBlocksToMaturity();
210 // Check if the block was requested by anyone
211 if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
212 status.status = TransactionStatus::MaturesWarning;
214 else
216 status.status = TransactionStatus::NotAccepted;
219 else
221 status.status = TransactionStatus::Confirmed;
224 else
226 if (status.depth < 0)
228 status.status = TransactionStatus::Conflicted;
230 else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
232 status.status = TransactionStatus::Offline;
234 else if (status.depth == 0)
236 status.status = TransactionStatus::Unconfirmed;
237 if (wtx.isAbandoned())
238 status.status = TransactionStatus::Abandoned;
240 else if (status.depth < RecommendedNumConfirmations)
242 status.status = TransactionStatus::Confirming;
244 else
246 status.status = TransactionStatus::Confirmed;
249 status.needsUpdate = false;
252 bool TransactionRecord::statusUpdateNeeded()
254 AssertLockHeld(cs_main);
255 return status.cur_num_blocks != chainActive.Height() || status.needsUpdate;
258 QString TransactionRecord::getTxID() const
260 return QString::fromStdString(hash.ToString());
263 int TransactionRecord::getOutputIndex() const
265 return idx;