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"
8 #include "consensus/consensus.h"
9 #include "validation.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
)
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.
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())
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
);
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();
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"];
70 sub
.type
= TransactionRecord::Generated
;
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
)
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
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
);
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.
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();
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 */
155 // Mixed debit transaction, can't break down payees
157 parts
.append(TransactionRecord(hash
, nTime
, TransactionRecord::Other
, "", nNet
, 0));
158 parts
.last().involvesWatchAddress
= involvesWatchAddress
;
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),
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();
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
;
216 status
.status
= TransactionStatus::NotAccepted
;
221 status
.status
= TransactionStatus::Confirmed
;
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
;
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