1 #include "transactionrecord.h"
6 extern CWallet* pwalletMain;
8 /* Return positive answer if transaction should be shown in list.
10 bool TransactionRecord::showTransaction(const CWalletTx &wtx)
14 // Ensures we show generated coins / mined transactions at depth 1
15 if (!wtx.IsInMainChain())
24 * Decompose CWallet transaction to model transaction records.
26 QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
28 QList<TransactionRecord> parts;
29 int64_t nTime = wtx.GetTxTime();
30 int64_t nCredit = wtx.GetCredit(MINE_ALL);
31 int64_t nDebit = wtx.GetDebit(MINE_ALL);
32 int64_t nNet = nCredit - nDebit;
33 uint256 hash = wtx.GetHash(), hashPrev = 0;
34 std::map<std::string, std::string> mapValue = wtx.mapValue;
36 if (nNet > 0 || wtx.IsCoinBase() || wtx.IsCoinStake())
41 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
43 if(wallet->IsMine(txout))
45 TransactionRecord sub(hash, nTime);
46 sub.idx = parts.size(); // sequence number
47 sub.credit = txout.nValue;
51 CTxDestination address;
52 if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
54 // Received by Bitcoin Address
55 sub.type = TransactionRecord::RecvWithAddress;
56 sub.address = CBitcoinAddress(address).ToString();
60 // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction
61 sub.type = TransactionRecord::RecvFromOther;
62 sub.address = mapValue["from"];
68 std::vector<valtype> vSolutions;
69 if (Solver(txout.scriptPubKey, whichType, vSolutions))
71 CTxDestination address;
72 if (whichType == TX_PUBKEY)
75 address = CPubKey(vSolutions[0]).GetID();
76 sub.type = TransactionRecord::RecvWithAddress;
77 sub.address = CBitcoinAddress(address).ToString();
79 else if (whichType == TX_PUBKEYHASH)
82 address = CKeyID(uint160(vSolutions[0]));
83 sub.type = TransactionRecord::RecvWithAddress;
84 sub.address = CBitcoinAddress(address).ToString();
86 else if (whichType == TX_SCRIPTHASH)
89 address = CScriptID(uint160(vSolutions[0]));
90 sub.type = TransactionRecord::RecvWithAddress;
91 sub.address = CBitcoinAddress(address).ToString();
93 else if (whichType == TX_PUBKEY_DROP)
96 sub.type = TransactionRecord::RecvWithAddress;
98 CMalleableKeyView view;
99 pwalletMain->CheckOwnership(CPubKey(vSolutions[0]), CPubKey(vSolutions[1]), view);
100 sub.address = view.GetMalleablePubKey().ToString();
104 // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction
105 sub.type = TransactionRecord::RecvFromOther;
106 sub.address = mapValue["from"];
110 if (wtx.IsCoinBase())
112 // Generated (proof-of-work)
113 sub.type = TransactionRecord::Generated;
115 if (wtx.IsCoinStake())
117 // Generated (proof-of-stake)
119 if (hashPrev == hash)
120 continue; // last coinstake output
122 sub.type = TransactionRecord::Generated;
123 sub.credit = nNet > 0 ? nNet : wtx.GetValueOut() - nDebit;
133 bool fAllFromMe = true;
134 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
135 fAllFromMe = fAllFromMe && wallet->IsMine(txin);
137 bool fAllToMe = true;
138 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
139 fAllToMe = fAllToMe && wallet->IsMine(txout);
141 if (fAllFromMe && fAllToMe)
144 int64_t nChange = wtx.GetChange();
146 parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "",
147 -(nDebit - nChange), nCredit - nChange));
154 int64_t nTxFee = nDebit - wtx.GetValueOut();
156 for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
158 const CTxOut& txout = wtx.vout[nOut];
159 TransactionRecord sub(hash, nTime);
160 sub.idx = parts.size();
162 if(wallet->IsMine(txout))
164 // Ignore parts sent to self, as this is usually the change
165 // from a transaction sent back to our own address.
169 CTxDestination address;
170 if (ExtractDestination(txout.scriptPubKey, address))
172 // Sent to Bitcoin Address
173 sub.type = TransactionRecord::SendToAddress;
174 sub.address = CBitcoinAddress(address).ToString();
178 // Sent to IP, or other non-address transaction like OP_EVAL
179 sub.type = TransactionRecord::SendToOther;
180 sub.address = mapValue["to"];
183 int64_t nValue = txout.nValue;
184 /* Add fee to first output */
198 // Mixed debit transaction, can't break down payees
200 parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0));
207 void TransactionRecord::updateStatus(const CWalletTx &wtx)
209 // Determine transaction status
211 // Find the block the tx is in
212 CBlockIndex* pindex = NULL;
213 std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(wtx.hashBlock);
214 if (mi != mapBlockIndex.end())
215 pindex = (*mi).second;
217 // Sort order, unrecorded transactions sort to the top
218 status.sortKey = strprintf("%010d-%01d-%010u-%03d",
219 (pindex ? pindex->nHeight : std::numeric_limits<int>::max()),
220 (wtx.IsCoinBase() ? 1 : 0),
223 status.confirmed = wtx.IsTrusted();
224 status.depth = wtx.GetDepthInMainChain();
225 status.cur_num_blocks = nBestHeight;
229 if (wtx.nLockTime < LOCKTIME_THRESHOLD)
231 status.status = TransactionStatus::OpenUntilBlock;
232 status.open_for = nBestHeight - wtx.nLockTime;
236 status.status = TransactionStatus::OpenUntilDate;
237 status.open_for = wtx.nLockTime;
242 if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
244 status.status = TransactionStatus::Offline;
246 else if (status.depth < NumConfirmations)
248 status.status = TransactionStatus::Unconfirmed;
252 status.status = TransactionStatus::HaveConfirmations;
256 // For generated transactions, determine maturity
257 if(type == TransactionRecord::Generated)
259 if (wtx.GetBlocksToMaturity() > 0)
261 status.maturity = TransactionStatus::Immature;
263 if (wtx.IsInMainChain())
265 status.matures_in = wtx.GetBlocksToMaturity();
267 // Check if the block was requested by anyone
268 if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
269 status.maturity = TransactionStatus::MaturesWarning;
273 status.maturity = TransactionStatus::NotAccepted;
278 status.maturity = TransactionStatus::Mature;
283 bool TransactionRecord::statusUpdateNeeded()
285 return status.cur_num_blocks != nBestHeight;
288 std::string TransactionRecord::getTxID()
290 return hash.ToString() + strprintf("-%03d", idx);