PIVX Core  5.6.99
P2P Digital Currency
transactionrecord.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2014 The Bitcoin developers
2 // Copyright (c) 2014-2015 The Dash developers
3 // Copyright (c) 2015-2022 The PIVX Core developers
4 // Distributed under the MIT software license, see the accompanying
5 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 
7 #include "transactionrecord.h"
8 
9 #include "key_io.h"
10 #include "budget/budgetproposal.h"
11 #include "sapling/key_io_sapling.h"
12 #include "wallet/wallet.h"
13 
14 #include <algorithm>
15 #include <stdint.h>
16 
17 std::string TransactionRecord::getValueOrReturnEmpty(const std::map<std::string, std::string>& mapValue, const std::string& key)
18 {
19  const auto& it = mapValue.find(key);
20  return it != mapValue.end() ? it->second : "";
21 }
22 
24  const CAmount& nCredit, const CAmount& nDebit,
25  QList<TransactionRecord>& parts)
26 {
27  // Return if it's not a coinstake
28  if (!wtx.IsCoinStake()) {
29  return false;
30  }
31 
32  const uint256& hash = wtx.GetHash();
33  TransactionRecord sub(hash, wtx.GetTxTime(), wtx.tx->GetTotalSize());
34 
35  if (isminetype mine = wallet->IsMine(wtx.tx->vout[1])) {
36  // Check for cold stakes.
37  if (wtx.tx->HasP2CSOutputs()) {
38  sub.credit = nCredit;
39  sub.debit = -nDebit;
40  loadHotOrColdStakeOrContract(wallet, wtx, sub);
41  } else {
42  // PIV stake reward
44  if (!ExtractDestination(wtx.tx->vout[1].scriptPubKey, address))
45  return true;
46 
50  sub.credit = nCredit - nDebit;
51  }
52  } else {
53  //Masternode reward
54  CTxDestination destMN;
55  int nIndexMN = (int) wtx.tx->vout.size() - 1;
56  if (ExtractDestination(wtx.tx->vout[nIndexMN].scriptPubKey, destMN) && (mine = IsMine(*wallet, destMN)) ) {
58  sub.address = EncodeDestination(destMN);
59  sub.credit = wtx.tx->vout[nIndexMN].nValue;
60  // Simple way to differentiate budget payments from MN rewards.
61  int nHeight = wtx.m_confirm.block_height;
64  }
65  }
66 
67  parts.append(sub);
68  return true;
69 }
70 
72  const CAmount& nCredit, const CAmount& nDebit,
73  QList<TransactionRecord>& parts)
74 {
75 
76  // Return if it's not a zc spend
77  if (!wtx.tx->HasZerocoinSpendInputs()) {
78  return false;
79  }
80 
81  // Basic values
82  const uint256& hash = wtx.GetHash();
83  int64_t nTime = wtx.GetTxTime();
84 
85  //zerocoin spend outputs
86  for (unsigned int nOut = 0; nOut < wtx.tx->vout.size(); nOut++) {
87  const CTxOut& txout = wtx.tx->vout[nOut];
88  // change that was reminted as zerocoins
89  if (txout.IsZerocoinMint()) {
90  continue;
91  }
92 
93  std::string strAddress;
96  strAddress = EncodeDestination(address);
97 
98  // a zerocoinspend that was sent to an address held by this wallet
99  isminetype mine = wallet->IsMine(txout);
100  if (mine) {
101  TransactionRecord sub(hash, nTime, wtx.tx->GetTotalSize());
104  sub.credit = txout.nValue;
105  sub.address = (!strAddress.empty()) ? strAddress : getValueOrReturnEmpty(wtx.mapValue, "recvzerocoinspend");
106  sub.idx = (int) nOut;
107  parts.append(sub);
108  continue;
109  }
110  }
111  return true;
112 }
113 
114 bool TransactionRecord::decomposeP2CS(const CWallet* wallet, const CWalletTx& wtx,
115  const CAmount& nCredit, const CAmount& nDebit,
116  QList<TransactionRecord>& parts)
117 {
118  if (wtx.tx->HasP2CSOutputs()) {
119  // Delegate tx.
120  TransactionRecord sub(wtx.GetHash(), wtx.GetTxTime(), wtx.tx->GetTotalSize());
121  sub.credit = nCredit;
122  sub.debit = -nDebit;
123  loadHotOrColdStakeOrContract(wallet, wtx, sub, true);
124  parts.append(sub);
125  return true;
126  } else if (wtx.HasP2CSInputs()) {
127  // Delegation unlocked
128  TransactionRecord sub(wtx.GetHash(), wtx.GetTxTime(), wtx.tx->GetTotalSize());
129  loadUnlockColdStake(wallet, wtx, sub);
130  parts.append(sub);
131  return true;
132  }
133  return false;
134 }
135 
139 bool TransactionRecord::decomposeCreditTransaction(const CWallet* wallet, const CWalletTx& wtx, QList<TransactionRecord>& parts)
140 {
141  TransactionRecord sub(wtx.GetHash(), wtx.GetTxTime(), wtx.tx->GetTotalSize());
142  for (unsigned int nOut = 0; nOut < wtx.tx->vout.size(); nOut++) {
143  const CTxOut& txout = wtx.tx->vout[nOut];
144  isminetype mine = wallet->IsMine(txout);
145  if (mine) {
147  sub.idx = (int) nOut; // vout index
148  sub.credit = txout.nValue;
150  if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) {
151  // Received by PIVX Address
154  } else {
155  // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction
157  sub.address = getValueOrReturnEmpty(wtx.mapValue, "from");
158  }
159  if (wtx.IsCoinBase()) {
160  // Generated
162  }
163 
164  parts.append(sub);
165  }
166  }
167 
168  if (wtx.tx->hasSaplingData()) {
169  auto sspkm = wallet->GetSaplingScriptPubKeyMan();
170  for (int i = 0; i < (int) wtx.tx->sapData->vShieldedOutput.size(); ++i) {
171  SaplingOutPoint out(sub.hash, i);
172  auto opAddr = sspkm->GetOutPointAddress(wtx, out);
173  if (opAddr) {
174  // skip it if change
175  if (sspkm->IsNoteSaplingChange(out, *opAddr)) {
176  continue;
177  }
178 
179  sub.address = (opAddr) ? KeyIO::EncodePaymentAddress(*opAddr) : "";
181  sub.credit = sspkm->GetOutPointValue(wtx, out);
182  sub.memo = sspkm->GetOutPointMemo(wtx, out);
183  if (sub.memo && !sub.memo->empty()) {
185  }
186  sub.idx = i;
187  parts.append(sub);
188  }
189  }
190  }
191 
192  return true;
193 }
194 
196  const CAmount& nDebit, bool involvesWatchAddress,
197  QList<TransactionRecord>& parts, const CWallet* wallet)
198 {
199  // Payment to self tx is presented as a single record.
200  TransactionRecord sub(wtx.GetHash(), wtx.GetTxTime(), wtx.tx->GetTotalSize());
201  sub.address = "";
202  CAmount nChange = wtx.GetChange();
203  if (!wtx.tx->hasSaplingData()) {
205  // Label for payment to self
207  if (ExtractDestination(wtx.tx->vout[0].scriptPubKey, address)) {
209  }
210  } else {
211  // we know that all of the inputs and outputs are mine and that have shielded data.
212  // Let's see if only have transparent inputs, so we know that this is a
213  // transparent -> shield transaction
214  const auto& sspkm = wallet->GetSaplingScriptPubKeyMan();
215  if (wtx.tx->sapData->vShieldedSpend.empty()) {
218  nChange += wtx.GetShieldedChange();
219 
220  SaplingOutPoint out(sub.hash, 0);
221  auto opAddr = sspkm->GetOutPointAddress(wtx, out);
222  if (opAddr) {
223  sub.address = KeyIO::EncodePaymentAddress(*opAddr);
224  }
225  sub.memo = sspkm->GetOutPointMemo(wtx, out);
226  } else {
227  // we know that the inputs are shielded now, let's see if
228  // if we have transparent outputs. if we have then we are converting back coins,
229  // from shield to transparent
230  if (!wtx.tx->vout.empty()) {
232  // Label for payment to self
234  if (ExtractDestination(wtx.tx->vout[0].scriptPubKey, address)) {
236  }
237  // little hack to show the correct amount
239  } else {
240  // we know that the outputs are only shield, this is purely a change address tx.
241  // show only the fee and eventually the memo (that for self s->s txs is put at 0 position).
243  SaplingOutPoint out(sub.hash, 0);
244  sub.memo = sspkm->GetOutPointMemo(wtx, out);
245  }
246  }
247  }
248 
249  sub.debit = -(nDebit - nChange);
250  sub.credit = nCredit - nChange;
252  parts.append(sub);
253  return true;
254 }
255 
257  bool involvesWatchAddress, QList<TransactionRecord>& parts)
258 {
259  // Return early if there are no outputs.
260  if (wtx.tx->sapData->vShieldedOutput.empty()) {
261  return false;
262  }
263 
264  TransactionRecord sub(wtx.GetHash(), wtx.GetTxTime(), wtx.tx->GetTotalSize());
265  auto sspkm = wallet->GetSaplingScriptPubKeyMan();
266  for (int i = 0; i < (int) wtx.tx->sapData->vShieldedOutput.size(); ++i) {
267  SaplingOutPoint out(sub.hash, i);
268  auto opAddr = sspkm->GetOutPointAddress(wtx, out);
269  // skip change
270  if (!opAddr || sspkm->IsNoteSaplingChange(out, *opAddr)) {
271  continue;
272  }
273  sub.idx = i;
276  sub.address = KeyIO::EncodePaymentAddress(*opAddr);
277  sub.memo = sspkm->GetOutPointMemo(wtx, out);
278  CAmount nValue = sspkm->GetOutPointValue(wtx, out);
279  /* Add fee to first output */
280  if (nTxFee > 0) {
281  nValue += nTxFee;
282  nTxFee = 0;
283  }
284  sub.debit = -nValue;
285  parts.append(sub);
286  }
287  return true;
288 }
289 
294  const CAmount& nDebit, bool involvesWatchAddress,
295  QList<TransactionRecord>& parts)
296 {
297  // Return early if there are no outputs.
298  if (wtx.tx->vout.empty() && wtx.tx->sapData->vShieldedOutput.empty()) {
299  return false;
300  }
301 
302  // GetValueOut is the sum of transparent outs and negative sapValueBalance (shielded outs minus shielded spends).
303  // Therefore to get the sum of the whole outputs of the tx, must re-add the shielded inputs spent to it
304  CAmount nTxFee = nDebit - (wtx.tx->GetValueOut() + wtx.GetDebit(ISMINE_SPENDABLE_SHIELDED | ISMINE_WATCH_ONLY_SHIELDED));
305  unsigned int txSize = wtx.tx->GetTotalSize();
306  const uint256& txHash = wtx.GetHash();
307  const int64_t txTime = wtx.GetTxTime();
308 
309  for (unsigned int nOut = 0; nOut < wtx.tx->vout.size(); nOut++) {
310  const CTxOut& txout = wtx.tx->vout[nOut];
311 
312  if (wallet->IsMine(txout)) {
313  // Ignore parts sent to self, as this is usually the change
314  // from a transaction sent back to our own address.
315  continue;
316  }
317 
318  // Create record
319  TransactionRecord sub(txHash, txTime, txSize);
320  sub.idx = (int) nOut;
322 
325  //This is most likely only going to happen when resyncing deterministic wallet without the knowledge of the
326  //private keys that the change was sent to. Do not display a "sent to" here.
327  if (wtx.tx->HasZerocoinMintOutputs())
328  continue;
329  // Sent to PIVX Address
332  } else if (txout.IsZerocoinMint()){
334  sub.address = getValueOrReturnEmpty(wtx.mapValue, "zerocoinmint");
335  sub.credit += txout.nValue;
336  } else {
337  // Sent to IP, or other non-address transaction like OP_EVAL
339  sub.address = getValueOrReturnEmpty(wtx.mapValue, "to");
340  if (sub.address.empty() && txout.scriptPubKey.StartsWithOpcode(OP_RETURN)) {
342  // Burned PIVs, op_return could be for a kind of data stored there. For now, support UTF8 comments.
343  std::string comment = wtx.GetComment();
344  if (!comment.empty() && IsValidUTF8(comment)) {
345  sub.address = comment;
346  }
347  // Check if this is a budget proposal fee (future: encapsulate functionality inside wallet/governanceModel)
348  std::string prop = getValueOrReturnEmpty(wtx.mapValue, "proposal");
349  if (!prop.empty()) {
350  const std::vector<unsigned char> vec = ParseHex(prop);
351  if (!vec.empty()) {
352  CDataStream ss(vec, SER_DISK, CLIENT_VERSION);
353  CBudgetProposal proposal;
354  ss >> proposal;
355  sub.address = "Proposal: " + proposal.GetName();
356  }
357  }
358  // future: could expand this to support base64 or hex encoded messages
359  }
360  }
361 
362  CAmount nValue = txout.nValue;
363  /* Add fee to first output */
364  if (nTxFee > 0) {
365  nValue += nTxFee;
366  nTxFee = 0;
367  }
368  sub.debit = -nValue;
369 
370  parts.append(sub);
371  }
372 
373  // Decompose shielded debit
374  return decomposeShieldedDebitTransaction(wallet, wtx, nTxFee, involvesWatchAddress, parts) || !parts.empty();
375 }
376 
377 // Check whether all the shielded inputs and outputs are from and send to this wallet
378 std::pair<bool, bool> areInputsAndOutputsFromAndToMe(const CWalletTx& wtx, SaplingScriptPubKeyMan* sspkm, bool& involvesWatchAddress)
379 {
380  // Check if all the shielded spends are from me
381  bool allShieldedSpendsFromMe = true;
382  for (const auto& spend : wtx.tx->sapData->vShieldedSpend) {
383  if (!sspkm->IsSaplingNullifierFromMe(spend.nullifier)) {
384  allShieldedSpendsFromMe = false;
385  break;
386  }
387  }
388 
389  // Check if all the shielded outputs are to me
390  bool allShieldedOutToMe = true;
391  for (int i = 0; i < (int) wtx.tx->sapData->vShieldedOutput.size(); ++i) {
392  SaplingOutPoint op(wtx.GetHash(), i);
393  isminetype mine = sspkm->IsMine(wtx, op);
394  if (mine & ISMINE_WATCH_ONLY_SHIELDED) involvesWatchAddress = true;
395  if (mine != ISMINE_SPENDABLE_SHIELDED) allShieldedOutToMe = false;
396  }
397 
398  return std::make_pair(allShieldedSpendsFromMe, allShieldedOutToMe);
399 }
400 
401 /*
402  * Decompose CWallet transaction to model transaction records.
403  */
404 QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet* wallet, const CWalletTx& wtx)
405 {
406  QList<TransactionRecord> parts;
407  CAmount nCredit = wtx.GetCredit(ISMINE_ALL);
408  CAmount nDebit = wtx.GetDebit(ISMINE_ALL);
409 
410  // Decompose coinstake if needed (if it's not a coinstake, the method will no perform any action).
411  if (decomposeCoinStake(wallet, wtx, nCredit, nDebit, parts)) {
412  return parts;
413  }
414 
415  // Decompose cold staking related transactions (with the exception of cold stakes that are decoupled in decomposeCoinStake)
416  // future: merge this flow with the 'credit/debit decomposing flow'.
417  if (decomposeP2CS(wallet, wtx, nCredit, nDebit, parts)) {
418  return parts;
419  }
420 
421  // Decompose zerocoin spend tx if needed (if it's not a zc spend, the method will not perform any action)
422  if (decomposeZcSpendTx(wallet, wtx, nCredit, nDebit, parts)) {
423  return parts;
424  }
425 
426  // Credit/Debit decomposing flow
427  CAmount nNet = nCredit - nDebit;
428 
429  // Check if the tx is credit and decompose it.
430  if (nNet > 0) {
431  // Decouple credit tx
432  if (decomposeCreditTransaction(wallet, wtx, parts)) {
433  return parts;
434  }
435  }
436 
437  auto sspkm = wallet->GetSaplingScriptPubKeyMan();
438  // As the tx is not credit, need to check if all the inputs and outputs are from and to this wallet.
439  // If it's true, then it's a sendToSelf. If not, then it's an outgoing tx.
440 
441  bool involvesWatchAddress = false;
442  isminetype fAllFromMe = ISMINE_SPENDABLE;
443  for (const CTxIn& txin : wtx.tx->vin) {
444  isminetype mine = wallet->IsMine(txin);
445  if (mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true;
446  if (fAllFromMe > mine) fAllFromMe = mine;
447  }
448 
449  isminetype fAllToMe = ISMINE_SPENDABLE;
450  for (const CTxOut& txout : wtx.tx->vout) {
451  isminetype mine = wallet->IsMine(txout);
452  if (mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true;
453  if (fAllToMe > mine) fAllToMe = mine;
454  }
455 
456  // Check whether all the shielded spends/outputs are from or to me.
457  bool allShieldedSpendsFromMe, allShieldedOutToMe = true;
458  std::tie(allShieldedSpendsFromMe, allShieldedOutToMe) =
460 
461  // Check if this tx is purely a payment to self.
462  if (fAllFromMe && fAllToMe && allShieldedOutToMe && allShieldedSpendsFromMe) {
463  // Single record for sendToSelf.
464  if (decomposeSendToSelfTransaction(wtx, nCredit, nDebit, involvesWatchAddress, parts, wallet)) {
465  return parts;
466  }
467  }
468 
469  // Check if the tx is debit and decompose it.
470  if (fAllFromMe || wtx.tx->HasZerocoinMintOutputs()) {
471  if (decomposeDebitTransaction(wallet, wtx, nDebit, involvesWatchAddress, parts)) {
472  return parts;
473  }
474  }
475 
476  // Check if wasn't able to decompose the transaction
477  if (parts.empty()) {
478  // if we get to this point, we have a mixed debit transaction, can't break down payees.
479  TransactionRecord record(wtx.GetHash(), wtx.GetTxTime(), wtx.tx->GetTotalSize(), TransactionRecord::Other, "", nNet,
480  0);
482  parts.append(record);
483  }
484  return parts;
485 }
486 
487 bool ExtractAddress(const CScript& scriptPubKey, bool fColdStake, std::string& addressStr) {
488  CTxDestination address;
489  if (!ExtractDestination(scriptPubKey, address, fColdStake)) {
490  // this shouldn't happen..
491  addressStr = "No available address";
492  return false;
493  } else {
494  addressStr = EncodeDestination(
495  address,
497  );
498  return true;
499  }
500 }
501 
503 {
504  record.involvesWatchAddress = false;
505 
506  // Get the p2cs
507  const CScript* p2csScript = nullptr;
508  bool isSpendable = false;
509 
510  for (const auto &input : wtx.tx->vin) {
511  const CWalletTx* tx = wallet->GetWalletTx(input.prevout.hash);
512  if (tx && tx->tx->vout[input.prevout.n].scriptPubKey.IsPayToColdStaking()) {
513  p2csScript = &tx->tx->vout[input.prevout.n].scriptPubKey;
514  isSpendable = wallet->IsMine(input) & ISMINE_SPENDABLE_ALL;
515  break;
516  }
517  }
518 
519  if (isSpendable) {
520  // owner unlocked the cold stake
522  record.debit = -(wtx.GetStakeDelegationDebit());
523  record.credit = wtx.GetCredit(ISMINE_ALL);
524  } else {
525  // hot node watching the unlock
527  record.debit = -(wtx.GetColdStakingDebit());
528  record.credit = -(wtx.GetColdStakingCredit());
529  }
530 
531  // Extract and set the owner address
532  if (p2csScript) {
533  ExtractAddress(*p2csScript, false, record.address);
534  }
535 }
536 
538  const CWallet* wallet,
539  const CWalletTx& wtx,
540  TransactionRecord& record,
541  bool isContract)
542 {
543  record.involvesWatchAddress = false;
544 
545  // Get the p2cs
546  CTxOut p2csUtxo;
547  for (const auto & txout : wtx.tx->vout) {
548  if (txout.scriptPubKey.IsPayToColdStaking()) {
549  p2csUtxo = txout;
550  break;
551  }
552  }
553 
554  bool isSpendable = (wallet->IsMine(p2csUtxo) & ISMINE_SPENDABLE_DELEGATED);
555  bool isFromMe = wallet->IsFromMe(wtx.tx);
556 
557  if (isContract) {
558  if (isSpendable && isFromMe) {
559  // Wallet delegating balance
561  } else if (isFromMe){
562  // Wallet delegating balance and transferring ownership
564  } else {
565  // Wallet receiving a delegation
567  }
568  } else {
569  // Stake
570  if (isSpendable) {
571  // Offline wallet receiving an stake due a delegation
574  record.debit = -(wtx.GetDebit(ISMINE_SPENDABLE_DELEGATED));
575  } else {
576  // Online wallet receiving an stake due a received utxo delegation that won a block.
578  }
579  }
580 
581  // Extract and set the owner address
582  ExtractAddress(p2csUtxo.scriptPubKey, false, record.address);
583 }
584 
585 void TransactionRecord::updateStatus(const CWalletTx& wtx, int chainHeight)
586 {
587  // Determine transaction status
588 
589  // Update time if needed
590  int64_t nTxTime = wtx.GetTxTime();
591  if (time != nTxTime) time = nTxTime;
592 
593  // Sort order, unrecorded transactions sort to the top
594  status.sortKey = strprintf("%010d-%01d-%010u-%03d",
596  ((wtx.IsCoinBase() || wtx.IsCoinStake()) ? 1 : 0),
597  time,
598  idx);
599 
600  bool fConflicted = false;
601  int depth = 0;
602  bool isTrusted = wtx.IsTrusted(depth, fConflicted);
603  int nBlocksToMaturity = (wtx.IsCoinBase() || wtx.IsCoinStake()) ? std::max(0, (Params().GetConsensus().nCoinbaseMaturity + 1) - depth) : 0;
604 
605  status.countsForBalance = isTrusted && !(nBlocksToMaturity > 0);
606  status.cur_num_blocks = chainHeight;
607  status.depth = depth;
608 
609  if (!IsFinalTx(wtx.tx, chainHeight + 1)) {
610  if (wtx.tx->nLockTime < LOCKTIME_THRESHOLD) {
612  status.open_for = wtx.tx->nLockTime - chainHeight;
613  } else {
615  status.open_for = wtx.tx->nLockTime;
616  }
617  }
618  // For generated transactions, determine maturity
619  else if (type == TransactionRecord::Generated ||
626 
627  if (nBlocksToMaturity > 0) {
629  status.matures_in = nBlocksToMaturity;
630 
631  if (status.depth < 0 || fConflicted) {
633  }
634  } else {
636  status.matures_in = 0;
637  }
638  } else {
639  if (status.depth < 0 || fConflicted) {
641  } else if (status.depth == 0) {
645  } else {
647  }
648  }
649  status.needsUpdate = false;
650 }
651 
652 bool TransactionRecord::statusUpdateNeeded(int blockHeight) const
653 {
654  return status.cur_num_blocks != blockHeight || status.needsUpdate;
655 }
656 
658 {
659  return idx;
660 }
661 
663 {
665 }
666 
668 {
670 }
671 
673 {
678 }
679 
681 {
682  return hash.IsNull() || size == 0;
683 }
684 
686  switch (status.status){
688  return "Confirmed";
690  return "OpenUntilDate";
692  return "OpenUntilBlock";
694  return "Unconfirmed";
696  return "Confirming";
698  return "Conflicted";
700  return "Immature";
702  return "Not Accepted";
703  default:
704  return "No status";
705  }
706 }
int64_t CAmount
Amount in PIV (Can be negative)
Definition: amount.h:13
const CChainParams & Params()
Return the currently selected parameters.
std::string GetName() const
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:72
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:381
bool StartsWithOpcode(const opcodetype opcode) const
Definition: script.cpp:265
An input of a transaction.
Definition: transaction.h:94
An output of a transaction.
Definition: transaction.h:137
CScript scriptPubKey
Definition: transaction.h:140
bool IsZerocoinMint() const
Definition: transaction.cpp:83
CAmount nValue
Definition: transaction.h:139
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,...
Definition: wallet.h:577
bool IsFromMe(const CTransactionRef &tx) const
should probably be renamed to IsRelevantToMe
Definition: wallet.cpp:4625
SaplingScriptPubKeyMan * GetSaplingScriptPubKeyMan() const
Definition: wallet.h:712
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:325
mapValue_t mapValue
Definition: wallet.h:335
CTransactionRef tx
Definition: wallet.h:364
bool HasP2CSInputs() const
checks whether a tx has P2CS inputs or not
Definition: wallet.cpp:4925
bool IsCoinStake() const
Definition: wallet.h:563
CAmount GetShieldedChange() const
Definition: wallet.cpp:4939
CAmount GetChange() const
Definition: wallet.cpp:4930
bool IsTrusted() const
Definition: wallet.cpp:4777
std::string GetComment() const
Definition: wallet.h:482
Confirmation m_confirm
Definition: wallet.h:394
const uint256 & GetHash() const
Definition: wallet.h:561
bool IsCoinBase() const
Definition: wallet.h:562
An outpoint - a combination of a transaction hash and an index n into its sapling output description ...
Definition: transaction.h:82
bool IsSaplingNullifierFromMe(const uint256 &nullifier) const
Whether the nullifier is from this wallet.
isminetype IsMine(const CWalletTx &wtx, const SaplingOutPoint &op) const
Return true if the wallet can decrypt & spend the shielded output.
UI model for a transaction.
bool isMNReward() const
Return true if the tx is a MN reward.
static bool decomposeShieldedDebitTransaction(const CWallet *wallet, const CWalletTx &wtx, CAmount nTxFee, bool involvesWatchAddress, QList< TransactionRecord > &parts)
std::string statusToString()
Return transaction status.
static std::string getValueOrReturnEmpty(const std::map< std::string, std::string > &mapValue, const std::string &key)
int idx
Subtransaction index, for sort key.
static void loadHotOrColdStakeOrContract(const CWallet *wallet, const CWalletTx &wtx, TransactionRecord &record, bool isContract=false)
static const int RecommendedNumConfirmations
Number of confirmation recommended for accepting a transaction.
Optional< CAmount > shieldedCredit
bool isCoinStake() const
Return true if the tx is a coinstake.
static void loadUnlockColdStake(const CWallet *wallet, const CWalletTx &wtx, TransactionRecord &record)
TransactionStatus status
Status: can change with block chain update.
void updateStatus(const CWalletTx &wtx, int chainHeight)
Update status from core wallet tx.
int getOutputIndex() const
Return the output index of the subtransaction
static bool decomposeCoinStake(const CWallet *wallet, const CWalletTx &wtx, const CAmount &nCredit, const CAmount &nDebit, QList< TransactionRecord > &parts)
Helpers.
static bool decomposeZcSpendTx(const CWallet *wallet, const CWalletTx &wtx, const CAmount &nCredit, const CAmount &nDebit, QList< TransactionRecord > &parts)
bool isAnyColdStakingType() const
Return true if the tx is a any cold staking type tx.
static bool decomposeCreditTransaction(const CWallet *wallet, const CWalletTx &wtx, QList< TransactionRecord > &parts)
Decompose a credit transaction into a record for each received output.
static bool decomposeDebitTransaction(const CWallet *wallet, const CWalletTx &wtx, const CAmount &nDebit, bool involvesWatchAddress, QList< TransactionRecord > &parts)
Decompose wtx outputs in records.
bool isNull() const
Return true if the tx hash is null and/or if the size is 0.
static QList< TransactionRecord > decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
Decompose CWallet transaction to model transaction records.
Optional< std::string > memo
bool statusUpdateNeeded(int blockHeight) const
Return whether a status update is needed.
static bool decomposeP2CS(const CWallet *wallet, const CWalletTx &wtx, const CAmount &nCredit, const CAmount &nDebit, QList< TransactionRecord > &parts)
bool involvesWatchAddress
Whether the transaction was sent/received with a watch-only address.
static bool decomposeSendToSelfTransaction(const CWalletTx &wtx, const CAmount &nCredit, const CAmount &nDebit, bool involvesWatchAddress, QList< TransactionRecord > &parts, const CWallet *wallet)
bool countsForBalance
Transaction counts towards available balance.
int cur_num_blocks
Current number of blocks (to know whether cached status is still valid)
@ Confirmed
Have 6 or more confirmations (normal tx) or fully mature (mined tx)
@ OpenUntilDate
Normal (sent/received) transactions.
@ Unconfirmed
Not yet mined into a block.
@ Immature
Generated (mined) transactions.
@ Confirming
Confirmed, but waiting for the recommended number of confirmations.
@ NotAccepted
Mined but not accepted.
@ OpenUntilBlock
Transaction not yet final, waiting for block.
@ Conflicted
Conflicts with other transaction or mempool.
qint64 open_for
Timestamp if status==OpenUntilDate, otherwise number of additional blocks that need to be mined befor...
std::string sortKey
Sorting key based on status.
bool IsNull() const
Definition: uint256.h:36
256-bit opaque blob.
Definition: uint256.h:138
CAmount GetColdStakingCredit(bool fUseCache=true) const
Definition: wallet.cpp:1694
isminetype IsMine(const CTxIn &txin) const
Definition: wallet.cpp:1448
CAmount GetDebit(const isminefilter &filter) const
filter decides which addresses will count towards the debit
Definition: wallet.cpp:1580
int64_t GetTxTime() const
Definition: wallet.cpp:1541
const CWalletTx * GetWalletTx(const uint256 &hash) const
Definition: wallet.cpp:166
CAmount GetCredit(const isminefilter &filter, bool recalculate=false) const
Definition: wallet.cpp:1616
CAmount GetColdStakingDebit(bool fUseCache=true) const
Definition: wallet.cpp:1606
CAmount GetStakeDelegationDebit(bool fUseCache=true) const
Definition: wallet.cpp:1611
isminetype IsMine(const CKeyStore &keystore, const CTxDestination &dest)
Definition: ismine.cpp:29
isminetype
IsMine() return codes.
Definition: ismine.h:19
@ ISMINE_ALL
Definition: ismine.h:35
@ ISMINE_SPENDABLE_ALL
Definition: ismine.h:33
@ ISMINE_SPENDABLE_SHIELDED
Indicates that we have the spending key of a shielded spend/output.
Definition: ismine.h:30
@ ISMINE_WATCH_ONLY_SHIELDED
Indicates that we don't have the spending key of a shielded spend/output.
Definition: ismine.h:28
@ ISMINE_SPENDABLE
Definition: ismine.h:22
@ ISMINE_WATCH_ONLY
Definition: ismine.h:21
@ ISMINE_SPENDABLE_TRANSPARENT
Definition: ismine.h:31
@ ISMINE_SPENDABLE_DELEGATED
Indicates that we have the spending key of a P2CS.
Definition: ismine.h:26
@ UPGRADE_V5_5
Definition: params.h:39
std::string EncodePaymentAddress(const libzcash::PaymentAddress &zaddr)
std::string EncodeDestination(const CWDestination &address, const CChainParams::Base58Type addrType)
@ OP_RETURN
Definition: script.h:87
@ SER_DISK
Definition: serialize.h:175
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet, bool fColdStake)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:162
boost::variant< CNoDestination, CKeyID, CScriptID, CExchangeKeyID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:72
CAmount nNewMNBlockReward
Definition: params.h:187
CAmount nMNBlockReward
Definition: params.h:186
bool NetworkUpgradeActive(int nHeight, Consensus::UpgradeIndex idx) const
Returns true if the given network upgrade is active as of the given block height.
Definition: params.cpp:12
#define strprintf
Definition: tinyformat.h:1056
std::pair< bool, bool > areInputsAndOutputsFromAndToMe(const CWalletTx &wtx, SaplingScriptPubKeyMan *sspkm, bool &involvesWatchAddress)
bool ExtractAddress(const CScript &scriptPubKey, bool fColdStake, std::string &addressStr)
bool IsFinalTx(const CTransactionRef &tx, int nBlockHeight, int64_t nBlockTime)
Check if transaction is final and can be included in a block with the specified height and time.
Definition: tx_verify.cpp:12
std::vector< unsigned char > ParseHex(const char *psz)
bool IsValidUTF8(const std::string &str)
Checks for valid 4-byte UTF-8 encoding in a string.