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"
16 /* Return positive answer if transaction should be shown in list.
18 bool TransactionRecord::showTransaction(const CWalletTx
&wtx
)
20 // There are currently no cases where we hide transactions, but
21 // we may want to use this in the future for things like RBF.
26 * Decompose CWallet transaction to model transaction records.
28 QList
<TransactionRecord
> TransactionRecord::decomposeTransaction(const CWallet
*wallet
, const CWalletTx
&wtx
)
30 QList
<TransactionRecord
> parts
;
31 int64_t nTime
= wtx
.GetTxTime();
32 CAmount nCredit
= wtx
.GetCredit(ISMINE_ALL
);
33 CAmount nDebit
= wtx
.GetDebit(ISMINE_ALL
);
34 CAmount nNet
= nCredit
- nDebit
;
35 uint256 hash
= wtx
.GetHash();
36 std::map
<std::string
, std::string
> mapValue
= wtx
.mapValue
;
38 if (nNet
> 0 || wtx
.IsCoinBase())
43 for(unsigned int i
= 0; i
< wtx
.tx
->vout
.size(); i
++)
45 const CTxOut
& txout
= wtx
.tx
->vout
[i
];
46 isminetype mine
= wallet
->IsMine(txout
);
49 TransactionRecord
sub(hash
, nTime
);
50 CTxDestination address
;
51 sub
.idx
= i
; // vout index
52 sub
.credit
= txout
.nValue
;
53 sub
.involvesWatchAddress
= mine
& ISMINE_WATCH_ONLY
;
54 if (ExtractDestination(txout
.scriptPubKey
, address
) && IsMine(*wallet
, address
))
56 // Received by Bitcoin Address
57 sub
.type
= TransactionRecord::RecvWithAddress
;
58 sub
.address
= CBitcoinAddress(address
).ToString();
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"];
69 sub
.type
= TransactionRecord::Generated
;
78 bool involvesWatchAddress
= false;
79 isminetype fAllFromMe
= ISMINE_SPENDABLE
;
80 for (const CTxIn
& txin
: wtx
.tx
->vin
)
82 isminetype mine
= wallet
->IsMine(txin
);
83 if(mine
& ISMINE_WATCH_ONLY
) involvesWatchAddress
= true;
84 if(fAllFromMe
> mine
) fAllFromMe
= mine
;
87 isminetype fAllToMe
= ISMINE_SPENDABLE
;
88 for (const CTxOut
& txout
: wtx
.tx
->vout
)
90 isminetype mine
= wallet
->IsMine(txout
);
91 if(mine
& ISMINE_WATCH_ONLY
) involvesWatchAddress
= true;
92 if(fAllToMe
> mine
) fAllToMe
= mine
;
95 if (fAllFromMe
&& fAllToMe
)
98 CAmount nChange
= wtx
.GetChange();
100 parts
.append(TransactionRecord(hash
, nTime
, TransactionRecord::SendToSelf
, "",
101 -(nDebit
- nChange
), nCredit
- nChange
));
102 parts
.last().involvesWatchAddress
= involvesWatchAddress
; // maybe pass to TransactionRecord as constructor argument
109 CAmount nTxFee
= nDebit
- wtx
.tx
->GetValueOut();
111 for (unsigned int nOut
= 0; nOut
< wtx
.tx
->vout
.size(); nOut
++)
113 const CTxOut
& txout
= wtx
.tx
->vout
[nOut
];
114 TransactionRecord
sub(hash
, nTime
);
116 sub
.involvesWatchAddress
= involvesWatchAddress
;
118 if(wallet
->IsMine(txout
))
120 // Ignore parts sent to self, as this is usually the change
121 // from a transaction sent back to our own address.
125 CTxDestination address
;
126 if (ExtractDestination(txout
.scriptPubKey
, address
))
128 // Sent to Bitcoin Address
129 sub
.type
= TransactionRecord::SendToAddress
;
130 sub
.address
= CBitcoinAddress(address
).ToString();
134 // Sent to IP, or other non-address transaction like OP_EVAL
135 sub
.type
= TransactionRecord::SendToOther
;
136 sub
.address
= mapValue
["to"];
139 CAmount nValue
= txout
.nValue
;
140 /* Add fee to first output */
154 // Mixed debit transaction, can't break down payees
156 parts
.append(TransactionRecord(hash
, nTime
, TransactionRecord::Other
, "", nNet
, 0));
157 parts
.last().involvesWatchAddress
= involvesWatchAddress
;
164 void TransactionRecord::updateStatus(const CWalletTx
&wtx
)
166 AssertLockHeld(cs_main
);
167 // Determine transaction status
169 // Find the block the tx is in
170 CBlockIndex
* pindex
= NULL
;
171 BlockMap::iterator mi
= mapBlockIndex
.find(wtx
.hashBlock
);
172 if (mi
!= mapBlockIndex
.end())
173 pindex
= (*mi
).second
;
175 // Sort order, unrecorded transactions sort to the top
176 status
.sortKey
= strprintf("%010d-%01d-%010u-%03d",
177 (pindex
? pindex
->nHeight
: std::numeric_limits
<int>::max()),
178 (wtx
.IsCoinBase() ? 1 : 0),
181 status
.countsForBalance
= wtx
.IsTrusted() && !(wtx
.GetBlocksToMaturity() > 0);
182 status
.depth
= wtx
.GetDepthInMainChain();
183 status
.cur_num_blocks
= chainActive
.Height();
185 if (!CheckFinalTx(wtx
))
187 if (wtx
.tx
->nLockTime
< LOCKTIME_THRESHOLD
)
189 status
.status
= TransactionStatus::OpenUntilBlock
;
190 status
.open_for
= wtx
.tx
->nLockTime
- chainActive
.Height();
194 status
.status
= TransactionStatus::OpenUntilDate
;
195 status
.open_for
= wtx
.tx
->nLockTime
;
198 // For generated transactions, determine maturity
199 else if(type
== TransactionRecord::Generated
)
201 if (wtx
.GetBlocksToMaturity() > 0)
203 status
.status
= TransactionStatus::Immature
;
205 if (wtx
.IsInMainChain())
207 status
.matures_in
= wtx
.GetBlocksToMaturity();
209 // Check if the block was requested by anyone
210 if (GetAdjustedTime() - wtx
.nTimeReceived
> 2 * 60 && wtx
.GetRequestCount() == 0)
211 status
.status
= TransactionStatus::MaturesWarning
;
215 status
.status
= TransactionStatus::NotAccepted
;
220 status
.status
= TransactionStatus::Confirmed
;
225 if (status
.depth
< 0)
227 status
.status
= TransactionStatus::Conflicted
;
229 else if (GetAdjustedTime() - wtx
.nTimeReceived
> 2 * 60 && wtx
.GetRequestCount() == 0)
231 status
.status
= TransactionStatus::Offline
;
233 else if (status
.depth
== 0)
235 status
.status
= TransactionStatus::Unconfirmed
;
236 if (wtx
.isAbandoned())
237 status
.status
= TransactionStatus::Abandoned
;
239 else if (status
.depth
< RecommendedNumConfirmations
)
241 status
.status
= TransactionStatus::Confirming
;
245 status
.status
= TransactionStatus::Confirmed
;
248 status
.needsUpdate
= false;
251 bool TransactionRecord::statusUpdateNeeded()
253 AssertLockHeld(cs_main
);
254 return status
.cur_num_blocks
!= chainActive
.Height() || status
.needsUpdate
;
257 QString
TransactionRecord::getTxID() const
259 return QString::fromStdString(hash
.ToString());
262 int TransactionRecord::getOutputIndex() const