Raven Core  3.0.0
P2P Digital Currency
transactionrecord.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2016 The Bitcoin Core developers
2 // Copyright (c) 2017-2019 The Raven 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 "assets/assets.h"
9 #include "base58.h"
10 #include "consensus/consensus.h"
11 #include "validation.h"
12 #include "timedata.h"
13 #include "wallet/wallet.h"
14 
15 #include <stdint.h>
16 
17 
18 /* Return positive answer if transaction should be shown in list.
19  */
21 {
22  // There are currently no cases where we hide transactions, but
23  // we may want to use this in the future for things like RBF.
24  return true;
25 }
26 
27 
28 /*
29  * Decompose CWallet transaction to model transaction records.
30  */
31 QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
32 {
33  QList<TransactionRecord> parts;
34  int64_t nTime = wtx.GetTxTime();
35  CAmount nCredit = wtx.GetCredit(ISMINE_ALL);
36  CAmount nDebit = wtx.GetDebit(ISMINE_ALL);
37  CAmount nNet = nCredit - nDebit;
38  uint256 hash = wtx.GetHash();
39  std::map<std::string, std::string> mapValue = wtx.mapValue;
40 
41  if (nNet > 0 || wtx.IsCoinBase())
42  {
43  //
44  // Credit
45  //
46  for(unsigned int i = 0; i < wtx.tx->vout.size(); i++)
47  {
48  const CTxOut& txout = wtx.tx->vout[i];
49  isminetype mine = wallet->IsMine(txout);
50 
53  continue;
56  if(mine)
57  {
58  TransactionRecord sub(hash, nTime);
60  sub.idx = i; // vout index
61  sub.credit = txout.nValue;
63  if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
64  {
65  // Received by Raven Address
67  sub.address = EncodeDestination(address);
68  }
69  else
70  {
71  // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction
73  sub.address = mapValue["from"];
74  }
75  if (wtx.IsCoinBase())
76  {
77  // Generated
79  }
80 
81  parts.append(sub);
82  }
83  }
84  }
85  else
86  {
87  bool involvesWatchAddress = false;
88  isminetype fAllFromMe = ISMINE_SPENDABLE;
89  for (const CTxIn& txin : wtx.tx->vin)
90  {
91  isminetype mine = wallet->IsMine(txin);
92  if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true;
93  if(fAllFromMe > mine) fAllFromMe = mine;
94  }
95 
96  isminetype fAllToMe = ISMINE_SPENDABLE;
97  for (const CTxOut& txout : wtx.tx->vout)
98  {
101  continue;
104  isminetype mine = wallet->IsMine(txout);
105  if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true;
106  if(fAllToMe > mine) fAllToMe = mine;
107  }
108 
109  if (fAllFromMe && fAllToMe)
110  {
111  // Payment to self
112  CAmount nChange = wtx.GetChange();
113 
114  parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "",
115  -(nDebit - nChange), nCredit - nChange));
116  parts.last().involvesWatchAddress = involvesWatchAddress; // maybe pass to TransactionRecord as constructor argument
117  }
118  else if (fAllFromMe)
119  {
120  //
121  // Debit
122  //
123  CAmount nTxFee = nDebit - wtx.tx->GetValueOut();
124 
125  for (unsigned int nOut = 0; nOut < wtx.tx->vout.size(); nOut++)
126  {
127  const CTxOut& txout = wtx.tx->vout[nOut];
128 
130  if (txout.scriptPubKey.IsAssetScript())
131  continue;
134  TransactionRecord sub(hash, nTime);
135  sub.idx = nOut;
137 
138  if(wallet->IsMine(txout))
139  {
140  // Ignore parts sent to self, as this is usually the change
141  // from a transaction sent back to our own address.
142  continue;
143  }
144 
146  if (ExtractDestination(txout.scriptPubKey, address))
147  {
148  // Sent to Raven Address
150  sub.address = EncodeDestination(address);
151  }
152  else
153  {
154  // Sent to IP, or other non-address transaction like OP_EVAL
156  sub.address = mapValue["to"];
157  }
158 
159  CAmount nValue = txout.nValue;
160  /* Add fee to first output */
161  if (nTxFee > 0)
162  {
163  nValue += nTxFee;
164  nTxFee = 0;
165  }
166  sub.debit = -nValue;
167 
168  parts.append(sub);
169  }
170  }
171  else
172  {
173  //
174  // Mixed debit transaction, can't break down payees
175  //
176 
177 
179  // We will only show mixed debit transactions that are nNet < 0 or if they are nNet == 0 and
180  // they do not contain assets. This is so the list of transaction doesn't add 0 amount transactions to the
181  // list.
182  bool fIsMixedDebit = true;
183  if (nNet == 0) {
184  for (unsigned int nOut = 0; nOut < wtx.tx->vout.size(); nOut++) {
185  const CTxOut &txout = wtx.tx->vout[nOut];
186 
188  fIsMixedDebit = false;
189  break;
190  }
191  }
192  }
193 
194  if (fIsMixedDebit) {
195  parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0));
196  parts.last().involvesWatchAddress = involvesWatchAddress;
197  }
199  }
200  }
201 
202 
204  if (AreAssetsDeployed()) {
205  CAmount nFee;
206  std::string strSentAccount;
207  std::list<COutputEntry> listReceived;
208  std::list<COutputEntry> listSent;
209 
210  std::list<CAssetOutputEntry> listAssetsReceived;
211  std::list<CAssetOutputEntry> listAssetsSent;
212 
213  wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, ISMINE_ALL, listAssetsReceived, listAssetsSent);
214 
215  if (listAssetsReceived.size() > 0)
216  {
217  for (const CAssetOutputEntry &data : listAssetsReceived)
218  {
219  TransactionRecord sub(hash, nTime);
220  sub.idx = data.vout;
221 
222  const CTxOut& txout = wtx.tx->vout[sub.idx];
223  isminetype mine = wallet->IsMine(txout);
224 
225  sub.address = EncodeDestination(data.destination);
226  sub.assetName = data.assetName;
227  sub.credit = data.nAmount;
229 
230  if (data.type == TX_NEW_ASSET)
232  else if (data.type == TX_REISSUE_ASSET)
234  else if (data.type == TX_TRANSFER_ASSET)
236  else {
238  }
239 
240  sub.units = DEFAULT_UNITS;
241 
242  if (IsAssetNameAnOwner(sub.assetName))
243  sub.units = OWNER_UNITS;
244  else if (CheckIssueDataTx(wtx.tx->vout[sub.idx]))
245  {
246  CNewAsset asset;
247  std::string strAddress;
248  if (AssetFromTransaction(wtx, asset, strAddress))
249  sub.units = asset.units;
250  }
251  else
252  {
253  CNewAsset asset;
254  if (passets->GetAssetMetaDataIfExists(sub.assetName, asset))
255  sub.units = asset.units;
256  }
257 
258  parts.append(sub);
259  }
260  }
261 
262  if (listAssetsSent.size() > 0)
263  {
264  for (const CAssetOutputEntry &data : listAssetsSent)
265  {
266  TransactionRecord sub(hash, nTime);
267  sub.idx = data.vout;
268  sub.address = EncodeDestination(data.destination);
269  sub.assetName = data.assetName;
270  sub.credit = -data.nAmount;
271  sub.involvesWatchAddress = false;
272 
273  if (data.type == TX_TRANSFER_ASSET)
275  else
277 
278  if (IsAssetNameAnOwner(sub.assetName))
279  sub.units = OWNER_UNITS;
280  else if (CheckIssueDataTx(wtx.tx->vout[sub.idx]))
281  {
282  CNewAsset asset;
283  std::string strAddress;
284  if (AssetFromTransaction(wtx, asset, strAddress))
285  sub.units = asset.units;
286  }
287  else
288  {
289  CNewAsset asset;
290  if (passets->GetAssetMetaDataIfExists(sub.assetName, asset))
291  sub.units = asset.units;
292  }
293 
294  parts.append(sub);
295  }
296  }
297  }
300  return parts;
301 }
302 
304 {
306  // Determine transaction status
307 
308  // Find the block the tx is in
309  CBlockIndex* pindex = nullptr;
310  BlockMap::iterator mi = mapBlockIndex.find(wtx.hashBlock);
311  if (mi != mapBlockIndex.end())
312  pindex = (*mi).second;
313 
314  // Sort order, unrecorded transactions sort to the top
315  status.sortKey = strprintf("%010d-%01d-%010u-%03d",
316  (pindex ? pindex->nHeight : std::numeric_limits<int>::max()),
317  (wtx.IsCoinBase() ? 1 : 0),
318  wtx.nTimeReceived,
319  idx);
320  status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0);
323 
324  if (!CheckFinalTx(wtx))
325  {
326  if (wtx.tx->nLockTime < LOCKTIME_THRESHOLD)
327  {
329  status.open_for = wtx.tx->nLockTime - chainActive.Height();
330  }
331  else
332  {
334  status.open_for = wtx.tx->nLockTime;
335  }
336  }
337  // For generated transactions, determine maturity
339  {
340  if (wtx.GetBlocksToMaturity() > 0)
341  {
343 
344  if (wtx.IsInMainChain())
345  {
347 
348  // Check if the block was requested by anyone
349  if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
351  }
352  else
353  {
355  }
356  }
357  else
358  {
360  }
361  }
362  else
363  {
364  if (status.depth < 0)
365  {
367  }
368  else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
369  {
371  }
372  else if (status.depth == 0)
373  {
375  if (wtx.isAbandoned())
377  }
379  {
381  }
382  else
383  {
385  }
386  }
387  status.needsUpdate = false;
388 }
389 
391 {
394 }
395 
397 {
398  return QString::fromStdString(hash.ToString());
399 }
400 
402 {
403  return idx;
404 }
CAmount nValue
Definition: transaction.h:140
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:89
Confirmed, but waiting for the recommended number of confirmations.
bool CheckIssueDataTx(const CTxOut &txOut)
issue asset scripts to make sure script meets the standards
Definition: assets.cpp:3068
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:210
Transaction not yet final, waiting for block.
int idx
Subtransaction index, for sort key.
int8_t units
Definition: assettypes.h:102
CScript scriptPubKey
Definition: transaction.h:141
Not sent to any other nodes.
Generated (mined) transactions.
#define strprintf
Definition: tinyformat.h:1054
const uint256 & GetHash() const
Definition: wallet.h:277
CAmount GetDebit(const isminefilter &filter) const
filter decides which addresses will count towards the debit
Definition: wallet.cpp:1745
Have 6 or more confirmations (normal tx) or fully mature (mined tx)
std::string sortKey
Sorting key based on status.
#define DEFAULT_UNITS
Definition: assets.h:26
int Height() const
Return the maximal height in the chain.
Definition: chain.h:479
uint256 hashBlock
Definition: wallet.h:212
CCriticalSection cs_main
Global state.
Definition: validation.cpp:72
bool AssetFromTransaction(const CTransaction &tx, CNewAsset &asset, std::string &strAddress)
These types of asset tx, have specific metadata at certain indexes in the transaction.
Definition: assets.cpp:525
Mined but not accepted.
Not yet mined into a block.
isminetype IsMine(const CKeyStore &keystore, const CScript &scriptPubKey, SigVersion sigversion)
Definition: ismine.cpp:32
static bool showTransaction(const CWalletTx &wtx)
Decompose CWallet transaction to model transaction records.
#define OWNER_UNITS
Definition: assets.h:34
RVN START.
Definition: wallet.h:191
mapValue_t mapValue
Key/value map with information about the transaction.
Definition: wallet.h:316
int64_t CAmount
Amount in corbies (Can be negative)
Definition: amount.h:13
#define AssertLockHeld(cs)
Definition: sync.h:86
int getOutputIndex() const
Return the output index of the subtransaction.
UI model for a transaction.
bool CheckFinalTx(const CTransaction &tx, int flags)
Transaction validation functions.
Definition: validation.cpp:255
TransactionStatus status
Status: can change with block chain update.
bool AreAssetsDeployed()
RVN START.
static QList< TransactionRecord > decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
CTransactionRef tx
Definition: wallet.h:211
bool GetAssetMetaDataIfExists(const std::string &name, CNewAsset &asset)
Returns true if an asset with the name exists, and it was able to get the asset metadata from databas...
Definition: assets.cpp:3340
isminetype
IsMine() return codes.
Definition: ismine.h:18
An input of a transaction.
Definition: transaction.h:67
QString getTxID() const
Return the unique identifier for this transaction (part)
bool IsCoinBase() const
Definition: wallet.h:278
int GetBlocksToMaturity() const
Definition: wallet.cpp:4783
bool countsForBalance
Transaction counts towards available balance.
void updateStatus(const CWalletTx &wtx)
Update status from core wallet tx.
bool IsTrusted() const
Definition: wallet.cpp:1911
bool statusUpdateNeeded() const
Return whether a status update is needed.
An output of a transaction.
Definition: transaction.h:137
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:75
std::string ToString() const
Definition: uint256.cpp:63
int cur_num_blocks
Current number of blocks (to know whether cached status is still valid)
Normal (sent/received) transactions.
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:285
bool IsInMainChain() const
Definition: wallet.h:269
256-bit opaque blob.
Definition: uint256.h:123
CAssetsCache * passets
Global variable that point to the active assets (protected by cs_main)
Definition: validation.cpp:227
std::string EncodeDestination(const CTxDestination &dest)
Definition: base58.cpp:326
CAmount GetCredit(const isminefilter &filter) const
Definition: wallet.cpp:1776
int64_t GetTxTime() const
Definition: wallet.cpp:1458
Conflicts with other transaction or mempool.
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:172
bool IsNullAssetTxDataScript() const
Definition: script.cpp:331
int64_t GetAdjustedTime()
Definition: timedata.cpp:36
bool involvesWatchAddress
Whether the transaction was sent/received with a watch-only address.
RVN START.
Definition: standard.h:69
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
Definition: wallet.h:673
unsigned int nTimeReceived
time received by this node
Definition: wallet.h:319
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:185
qint64 open_for
Timestamp if status==OpenUntilDate, otherwise number of additional blocks that need to be mined befor...
isminetype IsMine(const CTxIn &txin) const
Definition: wallet.cpp:1241
Abandoned from the wallet.
int GetDepthInMainChain(const CBlockIndex *&pindexRet) const
Return depth of transaction in blockchain: <0 : conflicts with a transaction this deep in the blockch...
Definition: wallet.cpp:4764
bool IsNullGlobalRestrictionAssetTxDataScript() const
Definition: script.cpp:338
BlockMap mapBlockIndex
Definition: validation.cpp:74
static const int RecommendedNumConfirmations
Number of confirmation recommended for accepting a transaction.
Transaction will likely not mature because no nodes have confirmed.
CAmount GetChange() const
Definition: wallet.cpp:1896
int GetRequestCount() const
Definition: wallet.cpp:1464
bool IsAssetNameAnOwner(const std::string &name)
Check if an asset is an owner.
Definition: assets.cpp:296
bool IsAssetScript(int &nType, bool &fIsOwner, int &nStartingIndex) const
Definition: script.cpp:245
bool isAbandoned() const
Definition: wallet.h:274
void GetAmounts(std::list< COutputEntry > &listReceived, std::list< COutputEntry > &listSent, CAmount &nFee, std::string &strSentAccount, const isminefilter &filter) const
Definition: wallet.cpp:1503