1 // Copyright (c) 2011-2015 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"
8 #include "consensus/consensus.h"
11 #include "wallet/wallet.h"
15 #include <boost/foreach.hpp>
17 /* Return positive answer if transaction should be shown in list.
19 bool TransactionRecord::showTransaction(const CWalletTx
&wtx
)
23 // Ensures we show generated coins / mined transactions at depth 1
24 if (!wtx
.IsInMainChain())
33 * Decompose CWallet transaction to model transaction records.
35 QList
<TransactionRecord
> TransactionRecord::decomposeTransaction(const CWallet
*wallet
, const CWalletTx
&wtx
)
37 QList
<TransactionRecord
> parts
;
38 int64_t nTime
= wtx
.GetTxTime();
39 CAmount nCredit
= wtx
.GetCredit(ISMINE_ALL
);
40 CAmount nDebit
= wtx
.GetDebit(ISMINE_ALL
);
41 CAmount nNet
= nCredit
- nDebit
;
42 uint256 hash
= wtx
.GetHash();
43 std::map
<std::string
, std::string
> mapValue
= wtx
.mapValue
;
45 if (nNet
> 0 || wtx
.IsCoinBase())
50 BOOST_FOREACH(const CTxOut
& txout
, wtx
.vout
)
52 isminetype mine
= wallet
->IsMine(txout
);
55 TransactionRecord
sub(hash
, nTime
);
56 CTxDestination address
;
57 sub
.idx
= parts
.size(); // sequence number
58 sub
.credit
= txout
.nValue
;
59 sub
.involvesWatchAddress
= mine
& ISMINE_WATCH_ONLY
;
60 if (ExtractDestination(txout
.scriptPubKey
, address
) && IsMine(*wallet
, address
))
62 // Received by Bitcoin Address
63 sub
.type
= TransactionRecord::RecvWithAddress
;
64 sub
.address
= CBitcoinAddress(address
).ToString();
68 // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction
69 sub
.type
= TransactionRecord::RecvFromOther
;
70 sub
.address
= mapValue
["from"];
75 sub
.type
= TransactionRecord::Generated
;
84 bool involvesWatchAddress
= false;
85 isminetype fAllFromMe
= ISMINE_SPENDABLE
;
86 BOOST_FOREACH(const CTxIn
& txin
, wtx
.vin
)
88 isminetype mine
= wallet
->IsMine(txin
);
89 if(mine
& ISMINE_WATCH_ONLY
) involvesWatchAddress
= true;
90 if(fAllFromMe
> mine
) fAllFromMe
= mine
;
93 isminetype fAllToMe
= ISMINE_SPENDABLE
;
94 BOOST_FOREACH(const CTxOut
& txout
, wtx
.vout
)
96 isminetype mine
= wallet
->IsMine(txout
);
97 if(mine
& ISMINE_WATCH_ONLY
) involvesWatchAddress
= true;
98 if(fAllToMe
> mine
) fAllToMe
= mine
;
101 if (fAllFromMe
&& fAllToMe
)
104 CAmount nChange
= wtx
.GetChange();
106 parts
.append(TransactionRecord(hash
, nTime
, TransactionRecord::SendToSelf
, "",
107 -(nDebit
- nChange
), nCredit
- nChange
));
108 parts
.last().involvesWatchAddress
= involvesWatchAddress
; // maybe pass to TransactionRecord as constructor argument
115 CAmount nTxFee
= nDebit
- wtx
.GetValueOut();
117 for (unsigned int nOut
= 0; nOut
< wtx
.vout
.size(); nOut
++)
119 const CTxOut
& txout
= wtx
.vout
[nOut
];
120 TransactionRecord
sub(hash
, nTime
);
121 sub
.idx
= parts
.size();
122 sub
.involvesWatchAddress
= involvesWatchAddress
;
124 if(wallet
->IsMine(txout
))
126 // Ignore parts sent to self, as this is usually the change
127 // from a transaction sent back to our own address.
131 CTxDestination address
;
132 if (ExtractDestination(txout
.scriptPubKey
, address
))
134 // Sent to Bitcoin Address
135 sub
.type
= TransactionRecord::SendToAddress
;
136 sub
.address
= CBitcoinAddress(address
).ToString();
140 // Sent to IP, or other non-address transaction like OP_EVAL
141 sub
.type
= TransactionRecord::SendToOther
;
142 sub
.address
= mapValue
["to"];
145 CAmount nValue
= txout
.nValue
;
146 /* Add fee to first output */
160 // Mixed debit transaction, can't break down payees
162 parts
.append(TransactionRecord(hash
, nTime
, TransactionRecord::Other
, "", nNet
, 0));
163 parts
.last().involvesWatchAddress
= involvesWatchAddress
;
170 void TransactionRecord::updateStatus(const CWalletTx
&wtx
)
172 AssertLockHeld(cs_main
);
173 // Determine transaction status
175 // Find the block the tx is in
176 CBlockIndex
* pindex
= NULL
;
177 BlockMap::iterator mi
= mapBlockIndex
.find(wtx
.hashBlock
);
178 if (mi
!= mapBlockIndex
.end())
179 pindex
= (*mi
).second
;
181 // Sort order, unrecorded transactions sort to the top
182 status
.sortKey
= strprintf("%010d-%01d-%010u-%03d",
183 (pindex
? pindex
->nHeight
: std::numeric_limits
<int>::max()),
184 (wtx
.IsCoinBase() ? 1 : 0),
187 status
.countsForBalance
= wtx
.IsTrusted() && !(wtx
.GetBlocksToMaturity() > 0);
188 status
.depth
= wtx
.GetDepthInMainChain();
189 status
.cur_num_blocks
= chainActive
.Height();
191 if (!CheckFinalTx(wtx
))
193 if (wtx
.nLockTime
< LOCKTIME_THRESHOLD
)
195 status
.status
= TransactionStatus::OpenUntilBlock
;
196 status
.open_for
= wtx
.nLockTime
- chainActive
.Height();
200 status
.status
= TransactionStatus::OpenUntilDate
;
201 status
.open_for
= wtx
.nLockTime
;
204 // For generated transactions, determine maturity
205 else if(type
== TransactionRecord::Generated
)
207 if (wtx
.GetBlocksToMaturity() > 0)
209 status
.status
= TransactionStatus::Immature
;
211 if (wtx
.IsInMainChain())
213 status
.matures_in
= wtx
.GetBlocksToMaturity();
215 // Check if the block was requested by anyone
216 if (GetAdjustedTime() - wtx
.nTimeReceived
> 2 * 60 && wtx
.GetRequestCount() == 0)
217 status
.status
= TransactionStatus::MaturesWarning
;
221 status
.status
= TransactionStatus::NotAccepted
;
226 status
.status
= TransactionStatus::Confirmed
;
231 if (status
.depth
< 0)
233 status
.status
= TransactionStatus::Conflicted
;
235 else if (GetAdjustedTime() - wtx
.nTimeReceived
> 2 * 60 && wtx
.GetRequestCount() == 0)
237 status
.status
= TransactionStatus::Offline
;
239 else if (status
.depth
== 0)
241 status
.status
= TransactionStatus::Unconfirmed
;
242 if (wtx
.isAbandoned())
243 status
.status
= TransactionStatus::Abandoned
;
245 else if (status
.depth
< RecommendedNumConfirmations
)
247 status
.status
= TransactionStatus::Confirming
;
251 status
.status
= TransactionStatus::Confirmed
;
257 bool TransactionRecord::statusUpdateNeeded()
259 AssertLockHeld(cs_main
);
260 return status
.cur_num_blocks
!= chainActive
.Height();
263 QString
TransactionRecord::getTxID() const
265 return QString::fromStdString(hash
.ToString());
268 int TransactionRecord::getOutputIndex() const