Dash Core  0.12.2.1
P2P Digital Currency
transactionrecord.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2015 The Bitcoin Core developers
2 // Copyright (c) 2014-2017 The Dash Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include "transactionrecord.h"
7 
8 #include "base58.h"
9 #include "consensus/consensus.h"
10 #include "validation.h"
11 #include "timedata.h"
12 #include "wallet/wallet.h"
13 
14 #include "instantx.h"
15 #include "privatesend.h"
16 
17 #include <stdint.h>
18 
19 #include <boost/foreach.hpp>
20 
21 /* Return positive answer if transaction should be shown in list.
22  */
24 {
25  if (wtx.IsCoinBase())
26  {
27  // Ensures we show generated coins / mined transactions at depth 1
28  if (!wtx.IsInMainChain())
29  {
30  return false;
31  }
32  }
33  return true;
34 }
35 
36 /*
37  * Decompose CWallet transaction to model transaction records.
38  */
39 QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
40 {
41  QList<TransactionRecord> parts;
42  int64_t nTime = wtx.GetTxTime();
43  CAmount nCredit = wtx.GetCredit(ISMINE_ALL);
44  CAmount nDebit = wtx.GetDebit(ISMINE_ALL);
45  CAmount nNet = nCredit - nDebit;
46  uint256 hash = wtx.GetHash();
47  std::map<std::string, std::string> mapValue = wtx.mapValue;
48 
49  if (nNet > 0 || wtx.IsCoinBase())
50  {
51  //
52  // Credit
53  //
54  BOOST_FOREACH(const CTxOut& txout, wtx.vout)
55  {
56  isminetype mine = wallet->IsMine(txout);
57  if(mine)
58  {
59  TransactionRecord sub(hash, nTime);
61  sub.idx = parts.size(); // sequence number
62  sub.credit = txout.nValue;
65  {
66  // Received by Dash Address
69  }
70  else
71  {
72  // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction
74  sub.address = mapValue["from"];
75  }
76  if (wtx.IsCoinBase())
77  {
78  // Generated
80  }
81 
82  parts.append(sub);
83  }
84  }
85  }
86  else
87  {
88  bool fAllFromMeDenom = true;
89  int nFromMe = 0;
90  bool involvesWatchAddress = false;
91  isminetype fAllFromMe = ISMINE_SPENDABLE;
92  BOOST_FOREACH(const CTxIn& txin, wtx.vin)
93  {
94  if(wallet->IsMine(txin)) {
95  fAllFromMeDenom = fAllFromMeDenom && wallet->IsDenominated(txin.prevout);
96  nFromMe++;
97  }
98  isminetype mine = wallet->IsMine(txin);
99  if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true;
100  if(fAllFromMe > mine) fAllFromMe = mine;
101  }
102 
103  isminetype fAllToMe = ISMINE_SPENDABLE;
104  bool fAllToMeDenom = true;
105  int nToMe = 0;
106  BOOST_FOREACH(const CTxOut& txout, wtx.vout) {
107  if(wallet->IsMine(txout)) {
108  fAllToMeDenom = fAllToMeDenom && wallet->IsDenominatedAmount(txout.nValue);
109  nToMe++;
110  }
111  isminetype mine = wallet->IsMine(txout);
112  if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true;
113  if(fAllToMe > mine) fAllToMe = mine;
114  }
115 
116  if(fAllFromMeDenom && fAllToMeDenom && nFromMe * nToMe) {
117  parts.append(TransactionRecord(hash, nTime, TransactionRecord::PrivateSendDenominate, "", -nDebit, nCredit));
118  parts.last().involvesWatchAddress = false; // maybe pass to TransactionRecord as constructor argument
119  }
120  else if (fAllFromMe && fAllToMe)
121  {
122  // Payment to self
123  // TODO: this section still not accurate but covers most cases,
124  // might need some additional work however
125 
126  TransactionRecord sub(hash, nTime);
127  // Payment to self by default
129  sub.address = "";
130 
131  if(mapValue["DS"] == "1")
132  {
135  if (ExtractDestination(wtx.vout[0].scriptPubKey, address))
136  {
137  // Sent to Dash Address
139  }
140  else
141  {
142  // Sent to IP, or other non-address transaction like OP_EVAL
143  sub.address = mapValue["to"];
144  }
145  }
146  else
147  {
148  for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
149  {
150  const CTxOut& txout = wtx.vout[nOut];
151  sub.idx = parts.size();
152 
153  if(wallet->IsCollateralAmount(txout.nValue)) sub.type = TransactionRecord::PrivateSendMakeCollaterals;
154  if(wallet->IsDenominatedAmount(txout.nValue)) sub.type = TransactionRecord::PrivateSendCreateDenominations;
156  }
157  }
158 
159  CAmount nChange = wtx.GetChange();
160 
161  sub.debit = -(nDebit - nChange);
162  sub.credit = nCredit - nChange;
163  parts.append(sub);
164  parts.last().involvesWatchAddress = involvesWatchAddress; // maybe pass to TransactionRecord as constructor argument
165  }
166  else if (fAllFromMe)
167  {
168  //
169  // Debit
170  //
171  CAmount nTxFee = nDebit - wtx.GetValueOut();
172 
173  for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
174  {
175  const CTxOut& txout = wtx.vout[nOut];
176  TransactionRecord sub(hash, nTime);
177  sub.idx = parts.size();
179 
180  if(wallet->IsMine(txout))
181  {
182  // Ignore parts sent to self, as this is usually the change
183  // from a transaction sent back to our own address.
184  continue;
185  }
186 
189  {
190  // Sent to Dash Address
193  }
194  else
195  {
196  // Sent to IP, or other non-address transaction like OP_EVAL
198  sub.address = mapValue["to"];
199  }
200 
201  if(mapValue["DS"] == "1")
202  {
204  }
205 
206  CAmount nValue = txout.nValue;
207  /* Add fee to first output */
208  if (nTxFee > 0)
209  {
210  nValue += nTxFee;
211  nTxFee = 0;
212  }
213  sub.debit = -nValue;
214 
215  parts.append(sub);
216  }
217  }
218  else
219  {
220  //
221  // Mixed debit transaction, can't break down payees
222  //
223  parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0));
224  parts.last().involvesWatchAddress = involvesWatchAddress;
225  }
226  }
227 
228  return parts;
229 }
230 
232 {
234  // Determine transaction status
235 
236  // Find the block the tx is in
237  CBlockIndex* pindex = NULL;
238  BlockMap::iterator mi = mapBlockIndex.find(wtx.hashBlock);
239  if (mi != mapBlockIndex.end())
240  pindex = (*mi).second;
241 
242  // Sort order, unrecorded transactions sort to the top
243  status.sortKey = strprintf("%010d-%01d-%010u-%03d",
244  (pindex ? pindex->nHeight : std::numeric_limits<int>::max()),
245  (wtx.IsCoinBase() ? 1 : 0),
246  wtx.nTimeReceived,
247  idx);
248  status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0);
252 
253  if (!CheckFinalTx(wtx))
254  {
255  if (wtx.nLockTime < LOCKTIME_THRESHOLD)
256  {
259  }
260  else
261  {
263  status.open_for = wtx.nLockTime;
264  }
265  }
266  // For generated transactions, determine maturity
268  {
269  if (wtx.GetBlocksToMaturity() > 0)
270  {
272 
273  if (wtx.IsInMainChain())
274  {
276 
277  // Check if the block was requested by anyone
278  if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
280  }
281  else
282  {
284  }
285  }
286  else
287  {
289  }
290  }
291  else
292  {
293  if (status.depth < 0)
294  {
296  }
297  else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
298  {
300  }
301  else if (status.depth == 0)
302  {
304  if (wtx.isAbandoned())
306  }
308  {
310  }
311  else
312  {
314  }
315  }
316 
317 }
318 
320 {
323 }
324 
326 {
327  return formatSubTxId(hash, idx);
328 }
329 
330 QString TransactionRecord::formatSubTxId(const uint256 &hash, int vout)
331 {
332  return QString::fromStdString(hash.ToString() + strprintf("-%03d", vout));
333 }
334 
void updateStatus(const CWalletTx &wtx)
CAmount GetCredit(const isminefilter &filter) const
Definition: wallet.cpp:1824
bool isAbandoned() const
Definition: wallet.h:267
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
Definition: standard.h:69
int nCompleteTXLocks
Definition: instantx.cpp:28
const uint32_t nLockTime
Definition: transaction.h:235
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Definition: standard.cpp:164
Normal (sent/received) transactions.
#define strprintf
Definition: tinyformat.h:1011
static bool showTransaction(const CWalletTx &wtx)
CCriticalSection cs_main
Definition: validation.cpp:62
isminetype IsMine(const CKeyStore &keystore, const CTxDestination &dest)
CAmount nValue
Definition: transaction.h:136
mapValue_t mapValue
Definition: wallet.h:281
std::string sortKey
Sorting key based on status.
static CAmount GetCollateralAmount()
Definition: privatesend.h:349
CAmount GetValueOut() const
TransactionStatus status
unsigned int nTimeReceived
Definition: wallet.h:284
CAmount GetChange() const
Definition: wallet.cpp:2023
bool IsInMainChain() const
Definition: wallet.h:263
std::string ToString() const
Definition: base58.cpp:193
int64_t CAmount
Definition: amount.h:14
#define AssertLockHeld(cs)
Definition: sync.h:96
bool CheckFinalTx(const CTransaction &tx, int flags)
Definition: validation.cpp:213
COutPoint prevout
Definition: transaction.h:61
int64_t GetTxTime() const
Definition: wallet.cpp:1540
int Height() const
Definition: chain.h:397
static QList< TransactionRecord > decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
static const int RecommendedNumConfirmations
CAmount GetDebit(const isminefilter &filter) const
filter decides which addresses will count towards the debit
Definition: wallet.cpp:1793
CChain chainActive
Definition: validation.cpp:65
std::string ToString() const
Definition: uint256.cpp:65
Definition: wallet.py:1
CScript scriptPubKey
Definition: transaction.h:137
const std::vector< CTxIn > vin
Definition: transaction.h:233
Generated (mined) transactions.
QString getTxID() const
static QString formatSubTxId(const uint256 &hash, int vout)
const uint256 & GetHash() const
Definition: transaction.h:262
int64_t GetAdjustedTime()
Definition: timedata.cpp:33
bool IsTrusted() const
Definition: wallet.cpp:2041
bool IsCoinBase() const
Definition: transaction.h:284
const std::vector< CTxOut > vout
Definition: transaction.h:234
bool countsForBalance
Transaction counts towards available balance.
static const unsigned int LOCKTIME_THRESHOLD
Definition: script.h:32
isminetype
Definition: wallet_ismine.h:17
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:113
int GetBlocksToMaturity() const
Definition: wallet.cpp:4449
int GetDepthInMainChain(const CBlockIndex *&pindexRet, bool enableIX=true) const
Definition: wallet.cpp:4416
BlockMap mapBlockIndex
Definition: validation.cpp:64
uint256 hashBlock
Definition: wallet.h:216
int GetRequestCount() const
Definition: wallet.cpp:1546