Bitcoin Core  22.99.0
P2P Digital Currency
transactions.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2021 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.
4 
5 #include <core_io.h>
6 #include <key_io.h>
7 #include <policy/rbf.h>
8 #include <rpc/util.h>
9 #include <util/vector.h>
10 #include <wallet/receive.h>
11 #include <wallet/rpc/util.h>
12 #include <wallet/wallet.h>
13 
15 
16 namespace wallet {
17 static void WalletTxToJSON(const CWallet& wallet, const CWalletTx& wtx, UniValue& entry)
18 {
19  interfaces::Chain& chain = wallet.chain();
20  int confirms = wallet.GetTxDepthInMainChain(wtx);
21  entry.pushKV("confirmations", confirms);
22  if (wtx.IsCoinBase())
23  entry.pushKV("generated", true);
24  if (auto* conf = wtx.state<TxStateConfirmed>())
25  {
26  entry.pushKV("blockhash", conf->confirmed_block_hash.GetHex());
27  entry.pushKV("blockheight", conf->confirmed_block_height);
28  entry.pushKV("blockindex", conf->position_in_block);
29  int64_t block_time;
30  CHECK_NONFATAL(chain.findBlock(conf->confirmed_block_hash, FoundBlock().time(block_time)));
31  entry.pushKV("blocktime", block_time);
32  } else {
33  entry.pushKV("trusted", CachedTxIsTrusted(wallet, wtx));
34  }
35  uint256 hash = wtx.GetHash();
36  entry.pushKV("txid", hash.GetHex());
37  UniValue conflicts(UniValue::VARR);
38  for (const uint256& conflict : wallet.GetTxConflicts(wtx))
39  conflicts.push_back(conflict.GetHex());
40  entry.pushKV("walletconflicts", conflicts);
41  entry.pushKV("time", wtx.GetTxTime());
42  entry.pushKV("timereceived", int64_t{wtx.nTimeReceived});
43 
44  // Add opt-in RBF status
45  std::string rbfStatus = "no";
46  if (confirms <= 0) {
47  RBFTransactionState rbfState = chain.isRBFOptIn(*wtx.tx);
48  if (rbfState == RBFTransactionState::UNKNOWN)
49  rbfStatus = "unknown";
50  else if (rbfState == RBFTransactionState::REPLACEABLE_BIP125)
51  rbfStatus = "yes";
52  }
53  entry.pushKV("bip125-replaceable", rbfStatus);
54 
55  for (const std::pair<const std::string, std::string>& item : wtx.mapValue)
56  entry.pushKV(item.first, item.second);
57 }
58 
59 struct tallyitem
60 {
62  int nConf{std::numeric_limits<int>::max()};
63  std::vector<uint256> txids;
64  bool fIsWatchonly{false};
66  {
67  }
68 };
69 
70 static UniValue ListReceived(const CWallet& wallet, const UniValue& params, const bool by_label, const bool include_immature_coinbase) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
71 {
72  // Minimum confirmations
73  int nMinDepth = 1;
74  if (!params[0].isNull())
75  nMinDepth = params[0].get_int();
76 
77  // Whether to include empty labels
78  bool fIncludeEmpty = false;
79  if (!params[1].isNull())
80  fIncludeEmpty = params[1].get_bool();
81 
83 
84  if (ParseIncludeWatchonly(params[2], wallet)) {
85  filter |= ISMINE_WATCH_ONLY;
86  }
87 
88  bool has_filtered_address = false;
89  CTxDestination filtered_address = CNoDestination();
90  if (!by_label && !params[3].isNull() && !params[3].get_str().empty()) {
91  if (!IsValidDestinationString(params[3].get_str())) {
92  throw JSONRPCError(RPC_WALLET_ERROR, "address_filter parameter was invalid");
93  }
94  filtered_address = DecodeDestination(params[3].get_str());
95  has_filtered_address = true;
96  }
97 
98  // Excluding coinbase outputs is deprecated
99  // It can be enabled by setting deprecatedrpc=exclude_coinbase
100  const bool include_coinbase{!wallet.chain().rpcEnableDeprecated("exclude_coinbase")};
101 
102  if (include_immature_coinbase && !include_coinbase) {
103  throw JSONRPCError(RPC_INVALID_PARAMETER, "include_immature_coinbase is incompatible with deprecated exclude_coinbase");
104  }
105 
106  // Tally
107  std::map<CTxDestination, tallyitem> mapTally;
108  for (const std::pair<const uint256, CWalletTx>& pairWtx : wallet.mapWallet) {
109  const CWalletTx& wtx = pairWtx.second;
110 
111  int nDepth = wallet.GetTxDepthInMainChain(wtx);
112  if (nDepth < nMinDepth)
113  continue;
114 
115  // Coinbase with less than 1 confirmation is no longer in the main chain
116  if ((wtx.IsCoinBase() && (nDepth < 1 || !include_coinbase))
117  || (wallet.IsTxImmatureCoinBase(wtx) && !include_immature_coinbase)
118  || !wallet.chain().checkFinalTx(*wtx.tx)) {
119  continue;
120  }
121 
122  for (const CTxOut& txout : wtx.tx->vout)
123  {
124  CTxDestination address;
125  if (!ExtractDestination(txout.scriptPubKey, address))
126  continue;
127 
128  if (has_filtered_address && !(filtered_address == address)) {
129  continue;
130  }
131 
132  isminefilter mine = wallet.IsMine(address);
133  if(!(mine & filter))
134  continue;
135 
136  tallyitem& item = mapTally[address];
137  item.nAmount += txout.nValue;
138  item.nConf = std::min(item.nConf, nDepth);
139  item.txids.push_back(wtx.GetHash());
140  if (mine & ISMINE_WATCH_ONLY)
141  item.fIsWatchonly = true;
142  }
143  }
144 
145  // Reply
147  std::map<std::string, tallyitem> label_tally;
148 
149  // Create m_address_book iterator
150  // If we aren't filtering, go from begin() to end()
151  auto start = wallet.m_address_book.begin();
152  auto end = wallet.m_address_book.end();
153  // If we are filtering, find() the applicable entry
154  if (has_filtered_address) {
155  start = wallet.m_address_book.find(filtered_address);
156  if (start != end) {
157  end = std::next(start);
158  }
159  }
160 
161  for (auto item_it = start; item_it != end; ++item_it)
162  {
163  if (item_it->second.IsChange()) continue;
164  const CTxDestination& address = item_it->first;
165  const std::string& label = item_it->second.GetLabel();
166  auto it = mapTally.find(address);
167  if (it == mapTally.end() && !fIncludeEmpty)
168  continue;
169 
170  CAmount nAmount = 0;
171  int nConf = std::numeric_limits<int>::max();
172  bool fIsWatchonly = false;
173  if (it != mapTally.end())
174  {
175  nAmount = (*it).second.nAmount;
176  nConf = (*it).second.nConf;
177  fIsWatchonly = (*it).second.fIsWatchonly;
178  }
179 
180  if (by_label)
181  {
182  tallyitem& _item = label_tally[label];
183  _item.nAmount += nAmount;
184  _item.nConf = std::min(_item.nConf, nConf);
185  _item.fIsWatchonly = fIsWatchonly;
186  }
187  else
188  {
190  if(fIsWatchonly)
191  obj.pushKV("involvesWatchonly", true);
192  obj.pushKV("address", EncodeDestination(address));
193  obj.pushKV("amount", ValueFromAmount(nAmount));
194  obj.pushKV("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf));
195  obj.pushKV("label", label);
196  UniValue transactions(UniValue::VARR);
197  if (it != mapTally.end())
198  {
199  for (const uint256& _item : (*it).second.txids)
200  {
201  transactions.push_back(_item.GetHex());
202  }
203  }
204  obj.pushKV("txids", transactions);
205  ret.push_back(obj);
206  }
207  }
208 
209  if (by_label)
210  {
211  for (const auto& entry : label_tally)
212  {
213  CAmount nAmount = entry.second.nAmount;
214  int nConf = entry.second.nConf;
216  if (entry.second.fIsWatchonly)
217  obj.pushKV("involvesWatchonly", true);
218  obj.pushKV("amount", ValueFromAmount(nAmount));
219  obj.pushKV("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf));
220  obj.pushKV("label", entry.first);
221  ret.push_back(obj);
222  }
223  }
224 
225  return ret;
226 }
227 
229 {
230  return RPCHelpMan{"listreceivedbyaddress",
231  "\nList balances by receiving address.\n",
232  {
233  {"minconf", RPCArg::Type::NUM, RPCArg::Default{1}, "The minimum number of confirmations before payments are included."},
234  {"include_empty", RPCArg::Type::BOOL, RPCArg::Default{false}, "Whether to include addresses that haven't received any payments."},
235  {"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Whether to include watch-only addresses (see 'importaddress')"},
236  {"address_filter", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "If present and non-empty, only return information on this address."},
237  {"include_immature_coinbase", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include immature coinbase transactions."},
238  },
239  RPCResult{
240  RPCResult::Type::ARR, "", "",
241  {
242  {RPCResult::Type::OBJ, "", "",
243  {
244  {RPCResult::Type::BOOL, "involvesWatchonly", /*optional=*/true, "Only returns true if imported addresses were involved in transaction"},
245  {RPCResult::Type::STR, "address", "The receiving address"},
246  {RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " received by the address"},
247  {RPCResult::Type::NUM, "confirmations", "The number of confirmations of the most recent transaction included"},
248  {RPCResult::Type::STR, "label", "The label of the receiving address. The default label is \"\""},
249  {RPCResult::Type::ARR, "txids", "",
250  {
251  {RPCResult::Type::STR_HEX, "txid", "The ids of transactions received with the address"},
252  }},
253  }},
254  }
255  },
256  RPCExamples{
257  HelpExampleCli("listreceivedbyaddress", "")
258  + HelpExampleCli("listreceivedbyaddress", "6 true")
259  + HelpExampleCli("listreceivedbyaddress", "6 true true \"\" true")
260  + HelpExampleRpc("listreceivedbyaddress", "6, true, true")
261  + HelpExampleRpc("listreceivedbyaddress", "6, true, true, \"" + EXAMPLE_ADDRESS[0] + "\", true")
262  },
263  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
264 {
265  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
266  if (!pwallet) return NullUniValue;
267 
268  // Make sure the results are valid at least up to the most recent block
269  // the user could have gotten from another RPC command prior to now
270  pwallet->BlockUntilSyncedToCurrentChain();
271 
272  const bool include_immature_coinbase{request.params[4].isNull() ? false : request.params[4].get_bool()};
273 
274  LOCK(pwallet->cs_wallet);
275 
276  return ListReceived(*pwallet, request.params, false, include_immature_coinbase);
277 },
278  };
279 }
280 
282 {
283  return RPCHelpMan{"listreceivedbylabel",
284  "\nList received transactions by label.\n",
285  {
286  {"minconf", RPCArg::Type::NUM, RPCArg::Default{1}, "The minimum number of confirmations before payments are included."},
287  {"include_empty", RPCArg::Type::BOOL, RPCArg::Default{false}, "Whether to include labels that haven't received any payments."},
288  {"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Whether to include watch-only addresses (see 'importaddress')"},
289  {"include_immature_coinbase", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include immature coinbase transactions."},
290  },
291  RPCResult{
292  RPCResult::Type::ARR, "", "",
293  {
294  {RPCResult::Type::OBJ, "", "",
295  {
296  {RPCResult::Type::BOOL, "involvesWatchonly", /*optional=*/true, "Only returns true if imported addresses were involved in transaction"},
297  {RPCResult::Type::STR_AMOUNT, "amount", "The total amount received by addresses with this label"},
298  {RPCResult::Type::NUM, "confirmations", "The number of confirmations of the most recent transaction included"},
299  {RPCResult::Type::STR, "label", "The label of the receiving address. The default label is \"\""},
300  }},
301  }
302  },
303  RPCExamples{
304  HelpExampleCli("listreceivedbylabel", "")
305  + HelpExampleCli("listreceivedbylabel", "6 true")
306  + HelpExampleRpc("listreceivedbylabel", "6, true, true, true")
307  },
308  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
309 {
310  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
311  if (!pwallet) return NullUniValue;
312 
313  // Make sure the results are valid at least up to the most recent block
314  // the user could have gotten from another RPC command prior to now
315  pwallet->BlockUntilSyncedToCurrentChain();
316 
317  const bool include_immature_coinbase{request.params[3].isNull() ? false : request.params[3].get_bool()};
318 
319  LOCK(pwallet->cs_wallet);
320 
321  return ListReceived(*pwallet, request.params, true, include_immature_coinbase);
322 },
323  };
324 }
325 
326 static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
327 {
328  if (IsValidDestination(dest)) {
329  entry.pushKV("address", EncodeDestination(dest));
330  }
331 }
332 
344 static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter_ismine, const std::string* filter_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
345 {
346  CAmount nFee;
347  std::list<COutputEntry> listReceived;
348  std::list<COutputEntry> listSent;
349 
350  CachedTxGetAmounts(wallet, wtx, listReceived, listSent, nFee, filter_ismine);
351 
352  bool involvesWatchonly = CachedTxIsFromMe(wallet, wtx, ISMINE_WATCH_ONLY);
353 
354  // Sent
355  if (!filter_label)
356  {
357  for (const COutputEntry& s : listSent)
358  {
359  UniValue entry(UniValue::VOBJ);
360  if (involvesWatchonly || (wallet.IsMine(s.destination) & ISMINE_WATCH_ONLY)) {
361  entry.pushKV("involvesWatchonly", true);
362  }
363  MaybePushAddress(entry, s.destination);
364  entry.pushKV("category", "send");
365  entry.pushKV("amount", ValueFromAmount(-s.amount));
366  const auto* address_book_entry = wallet.FindAddressBookEntry(s.destination);
367  if (address_book_entry) {
368  entry.pushKV("label", address_book_entry->GetLabel());
369  }
370  entry.pushKV("vout", s.vout);
371  entry.pushKV("fee", ValueFromAmount(-nFee));
372  if (fLong)
373  WalletTxToJSON(wallet, wtx, entry);
374  entry.pushKV("abandoned", wtx.isAbandoned());
375  ret.push_back(entry);
376  }
377  }
378 
379  // Received
380  if (listReceived.size() > 0 && wallet.GetTxDepthInMainChain(wtx) >= nMinDepth) {
381  for (const COutputEntry& r : listReceived)
382  {
383  std::string label;
384  const auto* address_book_entry = wallet.FindAddressBookEntry(r.destination);
385  if (address_book_entry) {
386  label = address_book_entry->GetLabel();
387  }
388  if (filter_label && label != *filter_label) {
389  continue;
390  }
391  UniValue entry(UniValue::VOBJ);
392  if (involvesWatchonly || (wallet.IsMine(r.destination) & ISMINE_WATCH_ONLY)) {
393  entry.pushKV("involvesWatchonly", true);
394  }
395  MaybePushAddress(entry, r.destination);
396  if (wtx.IsCoinBase())
397  {
398  if (wallet.GetTxDepthInMainChain(wtx) < 1)
399  entry.pushKV("category", "orphan");
400  else if (wallet.IsTxImmatureCoinBase(wtx))
401  entry.pushKV("category", "immature");
402  else
403  entry.pushKV("category", "generate");
404  }
405  else
406  {
407  entry.pushKV("category", "receive");
408  }
409  entry.pushKV("amount", ValueFromAmount(r.amount));
410  if (address_book_entry) {
411  entry.pushKV("label", label);
412  }
413  entry.pushKV("vout", r.vout);
414  if (fLong)
415  WalletTxToJSON(wallet, wtx, entry);
416  ret.push_back(entry);
417  }
418  }
419 }
420 
421 
422 static const std::vector<RPCResult> TransactionDescriptionString()
423 {
424  return{{RPCResult::Type::NUM, "confirmations", "The number of confirmations for the transaction. Negative confirmations means the\n"
425  "transaction conflicted that many blocks ago."},
426  {RPCResult::Type::BOOL, "generated", /*optional=*/true, "Only present if the transaction's only input is a coinbase one."},
427  {RPCResult::Type::BOOL, "trusted", /*optional=*/true, "Whether we consider the transaction to be trusted and safe to spend from.\n"
428  "Only present when the transaction has 0 confirmations (or negative confirmations, if conflicted)."},
429  {RPCResult::Type::STR_HEX, "blockhash", /*optional=*/true, "The block hash containing the transaction."},
430  {RPCResult::Type::NUM, "blockheight", /*optional=*/true, "The block height containing the transaction."},
431  {RPCResult::Type::NUM, "blockindex", /*optional=*/true, "The index of the transaction in the block that includes it."},
432  {RPCResult::Type::NUM_TIME, "blocktime", /*optional=*/true, "The block time expressed in " + UNIX_EPOCH_TIME + "."},
433  {RPCResult::Type::STR_HEX, "txid", "The transaction id."},
434  {RPCResult::Type::ARR, "walletconflicts", "Conflicting transaction ids.",
435  {
436  {RPCResult::Type::STR_HEX, "txid", "The transaction id."},
437  }},
438  {RPCResult::Type::STR_HEX, "replaced_by_txid", /*optional=*/true, "The txid if this tx was replaced."},
439  {RPCResult::Type::STR_HEX, "replaces_txid", /*optional=*/true, "The txid if the tx replaces one."},
440  {RPCResult::Type::STR, "comment", /*optional=*/true, ""},
441  {RPCResult::Type::STR, "to", /*optional=*/true, "If a comment to is associated with the transaction."},
442  {RPCResult::Type::NUM_TIME, "time", "The transaction time expressed in " + UNIX_EPOCH_TIME + "."},
443  {RPCResult::Type::NUM_TIME, "timereceived", "The time received expressed in " + UNIX_EPOCH_TIME + "."},
444  {RPCResult::Type::STR, "comment", /*optional=*/true, "If a comment is associated with the transaction, only present if not empty."},
445  {RPCResult::Type::STR, "bip125-replaceable", "(\"yes|no|unknown\") Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
446  "may be unknown for unconfirmed transactions not in the mempool."}};
447 }
448 
450 {
451  return RPCHelpMan{"listtransactions",
452  "\nIf a label name is provided, this will return only incoming transactions paying to addresses with the specified label.\n"
453  "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions.\n",
454  {
455  {"label|dummy", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "If set, should be a valid label name to return only incoming transactions\n"
456  "with the specified label, or \"*\" to disable filtering and return all transactions."},
457  {"count", RPCArg::Type::NUM, RPCArg::Default{10}, "The number of transactions to return"},
458  {"skip", RPCArg::Type::NUM, RPCArg::Default{0}, "The number of transactions to skip"},
459  {"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Include transactions to watch-only addresses (see 'importaddress')"},
460  },
461  RPCResult{
462  RPCResult::Type::ARR, "", "",
463  {
464  {RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>(
465  {
466  {RPCResult::Type::BOOL, "involvesWatchonly", /*optional=*/true, "Only returns true if imported addresses were involved in transaction."},
467  {RPCResult::Type::STR, "address", "The bitcoin address of the transaction."},
468  {RPCResult::Type::STR, "category", "The transaction category.\n"
469  "\"send\" Transactions sent.\n"
470  "\"receive\" Non-coinbase transactions received.\n"
471  "\"generate\" Coinbase transactions received with more than 100 confirmations.\n"
472  "\"immature\" Coinbase transactions received with 100 or fewer confirmations.\n"
473  "\"orphan\" Orphaned coinbase transactions received."},
474  {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n"
475  "for all other categories"},
476  {RPCResult::Type::STR, "label", /*optional=*/true, "A comment for the address/transaction, if any"},
477  {RPCResult::Type::NUM, "vout", "the vout value"},
478  {RPCResult::Type::STR_AMOUNT, "fee", /*optional=*/true, "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n"
479  "'send' category of transactions."},
480  },
482  {
483  {RPCResult::Type::BOOL, "abandoned", /*optional=*/true, "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
484  "'send' category of transactions."},
485  })},
486  }
487  },
488  RPCExamples{
489  "\nList the most recent 10 transactions in the systems\n"
490  + HelpExampleCli("listtransactions", "") +
491  "\nList transactions 100 to 120\n"
492  + HelpExampleCli("listtransactions", "\"*\" 20 100") +
493  "\nAs a JSON-RPC call\n"
494  + HelpExampleRpc("listtransactions", "\"*\", 20, 100")
495  },
496  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
497 {
498  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
499  if (!pwallet) return NullUniValue;
500 
501  // Make sure the results are valid at least up to the most recent block
502  // the user could have gotten from another RPC command prior to now
503  pwallet->BlockUntilSyncedToCurrentChain();
504 
505  const std::string* filter_label = nullptr;
506  if (!request.params[0].isNull() && request.params[0].get_str() != "*") {
507  filter_label = &request.params[0].get_str();
508  if (filter_label->empty()) {
509  throw JSONRPCError(RPC_INVALID_PARAMETER, "Label argument must be a valid label name or \"*\".");
510  }
511  }
512  int nCount = 10;
513  if (!request.params[1].isNull())
514  nCount = request.params[1].get_int();
515  int nFrom = 0;
516  if (!request.params[2].isNull())
517  nFrom = request.params[2].get_int();
519 
520  if (ParseIncludeWatchonly(request.params[3], *pwallet)) {
521  filter |= ISMINE_WATCH_ONLY;
522  }
523 
524  if (nCount < 0)
525  throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
526  if (nFrom < 0)
527  throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
528 
530 
531  {
532  LOCK(pwallet->cs_wallet);
533 
534  const CWallet::TxItems & txOrdered = pwallet->wtxOrdered;
535 
536  // iterate backwards until we have nCount items to return:
537  for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
538  {
539  CWalletTx *const pwtx = (*it).second;
540  ListTransactions(*pwallet, *pwtx, 0, true, ret, filter, filter_label);
541  if ((int)ret.size() >= (nCount+nFrom)) break;
542  }
543  }
544 
545  // ret is newest to oldest
546 
547  if (nFrom > (int)ret.size())
548  nFrom = ret.size();
549  if ((nFrom + nCount) > (int)ret.size())
550  nCount = ret.size() - nFrom;
551 
552  const std::vector<UniValue>& txs = ret.getValues();
553  UniValue result{UniValue::VARR};
554  result.push_backV({ txs.rend() - nFrom - nCount, txs.rend() - nFrom }); // Return oldest to newest
555  return result;
556 },
557  };
558 }
559 
561 {
562  return RPCHelpMan{"listsinceblock",
563  "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted.\n"
564  "If \"blockhash\" is no longer a part of the main chain, transactions from the fork point onward are included.\n"
565  "Additionally, if include_removed is set, transactions affecting the wallet which were removed are returned in the \"removed\" array.\n",
566  {
567  {"blockhash", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "If set, the block hash to list transactions since, otherwise list all transactions."},
568  {"target_confirmations", RPCArg::Type::NUM, RPCArg::Default{1}, "Return the nth block hash from the main chain. e.g. 1 would mean the best block hash. Note: this is not used as a filter, but only affects [lastblock] in the return value"},
569  {"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Include transactions to watch-only addresses (see 'importaddress')"},
570  {"include_removed", RPCArg::Type::BOOL, RPCArg::Default{true}, "Show transactions that were removed due to a reorg in the \"removed\" array\n"
571  "(not guaranteed to work on pruned nodes)"},
572  },
573  RPCResult{
574  RPCResult::Type::OBJ, "", "",
575  {
576  {RPCResult::Type::ARR, "transactions", "",
577  {
578  {RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>(
579  {
580  {RPCResult::Type::BOOL, "involvesWatchonly", /*optional=*/true, "Only returns true if imported addresses were involved in transaction."},
581  {RPCResult::Type::STR, "address", "The bitcoin address of the transaction."},
582  {RPCResult::Type::STR, "category", "The transaction category.\n"
583  "\"send\" Transactions sent.\n"
584  "\"receive\" Non-coinbase transactions received.\n"
585  "\"generate\" Coinbase transactions received with more than 100 confirmations.\n"
586  "\"immature\" Coinbase transactions received with 100 or fewer confirmations.\n"
587  "\"orphan\" Orphaned coinbase transactions received."},
588  {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n"
589  "for all other categories"},
590  {RPCResult::Type::NUM, "vout", "the vout value"},
591  {RPCResult::Type::STR_AMOUNT, "fee", /*optional=*/true, "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n"
592  "'send' category of transactions."},
593  },
595  {
596  {RPCResult::Type::BOOL, "abandoned", /*optional=*/true, "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
597  "'send' category of transactions."},
598  {RPCResult::Type::STR, "label", /*optional=*/true, "A comment for the address/transaction, if any"},
599  })},
600  }},
601  {RPCResult::Type::ARR, "removed", /*optional=*/true, "<structure is the same as \"transactions\" above, only present if include_removed=true>\n"
602  "Note: transactions that were re-added in the active chain will appear as-is in this array, and may thus have a positive confirmation count."
603  , {{RPCResult::Type::ELISION, "", ""},}},
604  {RPCResult::Type::STR_HEX, "lastblock", "The hash of the block (target_confirmations-1) from the best block on the main chain, or the genesis hash if the referenced block does not exist yet. This is typically used to feed back into listsinceblock the next time you call it. So you would generally use a target_confirmations of say 6, so you will be continually re-notified of transactions until they've reached 6 confirmations plus any new ones"},
605  }
606  },
607  RPCExamples{
608  HelpExampleCli("listsinceblock", "")
609  + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
610  + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
611  },
612  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
613 {
614  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
615  if (!pwallet) return NullUniValue;
616 
617  const CWallet& wallet = *pwallet;
618  // Make sure the results are valid at least up to the most recent block
619  // the user could have gotten from another RPC command prior to now
620  wallet.BlockUntilSyncedToCurrentChain();
621 
622  LOCK(wallet.cs_wallet);
623 
624  std::optional<int> height; // Height of the specified block or the common ancestor, if the block provided was in a deactivated chain.
625  std::optional<int> altheight; // Height of the specified block, even if it's in a deactivated chain.
626  int target_confirms = 1;
628 
629  uint256 blockId;
630  if (!request.params[0].isNull() && !request.params[0].get_str().empty()) {
631  blockId = ParseHashV(request.params[0], "blockhash");
632  height = int{};
633  altheight = int{};
634  if (!wallet.chain().findCommonAncestor(blockId, wallet.GetLastBlockHash(), /* ancestor out */ FoundBlock().height(*height), /* blockId out */ FoundBlock().height(*altheight))) {
635  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
636  }
637  }
638 
639  if (!request.params[1].isNull()) {
640  target_confirms = request.params[1].get_int();
641 
642  if (target_confirms < 1) {
643  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
644  }
645  }
646 
647  if (ParseIncludeWatchonly(request.params[2], wallet)) {
648  filter |= ISMINE_WATCH_ONLY;
649  }
650 
651  bool include_removed = (request.params[3].isNull() || request.params[3].get_bool());
652 
653  int depth = height ? wallet.GetLastBlockHeight() + 1 - *height : -1;
654 
655  UniValue transactions(UniValue::VARR);
656 
657  for (const std::pair<const uint256, CWalletTx>& pairWtx : wallet.mapWallet) {
658  const CWalletTx& tx = pairWtx.second;
659 
660  if (depth == -1 || abs(wallet.GetTxDepthInMainChain(tx)) < depth) {
661  ListTransactions(wallet, tx, 0, true, transactions, filter, nullptr /* filter_label */);
662  }
663  }
664 
665  // when a reorg'd block is requested, we also list any relevant transactions
666  // in the blocks of the chain that was detached
667  UniValue removed(UniValue::VARR);
668  while (include_removed && altheight && *altheight > *height) {
669  CBlock block;
670  if (!wallet.chain().findBlock(blockId, FoundBlock().data(block)) || block.IsNull()) {
671  throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
672  }
673  for (const CTransactionRef& tx : block.vtx) {
674  auto it = wallet.mapWallet.find(tx->GetHash());
675  if (it != wallet.mapWallet.end()) {
676  // We want all transactions regardless of confirmation count to appear here,
677  // even negative confirmation ones, hence the big negative.
678  ListTransactions(wallet, it->second, -100000000, true, removed, filter, nullptr /* filter_label */);
679  }
680  }
681  blockId = block.hashPrevBlock;
682  --*altheight;
683  }
684 
685  uint256 lastblock;
686  target_confirms = std::min(target_confirms, wallet.GetLastBlockHeight() + 1);
687  CHECK_NONFATAL(wallet.chain().findAncestorByHeight(wallet.GetLastBlockHash(), wallet.GetLastBlockHeight() + 1 - target_confirms, FoundBlock().hash(lastblock)));
688 
690  ret.pushKV("transactions", transactions);
691  if (include_removed) ret.pushKV("removed", removed);
692  ret.pushKV("lastblock", lastblock.GetHex());
693 
694  return ret;
695 },
696  };
697 }
698 
700 {
701  return RPCHelpMan{"gettransaction",
702  "\nGet detailed information about in-wallet transaction <txid>\n",
703  {
704  {"txid", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction id"},
705  {"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"},
706  "Whether to include watch-only addresses in balance calculation and details[]"},
707  {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false},
708  "Whether to include a `decoded` field containing the decoded transaction (equivalent to RPC decoderawtransaction)"},
709  },
710  RPCResult{
711  RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>(
712  {
713  {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT},
714  {RPCResult::Type::STR_AMOUNT, "fee", /*optional=*/true, "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n"
715  "'send' category of transactions."},
716  },
718  {
719  {RPCResult::Type::ARR, "details", "",
720  {
721  {RPCResult::Type::OBJ, "", "",
722  {
723  {RPCResult::Type::BOOL, "involvesWatchonly", /*optional=*/true, "Only returns true if imported addresses were involved in transaction."},
724  {RPCResult::Type::STR, "address", /*optional=*/true, "The bitcoin address involved in the transaction."},
725  {RPCResult::Type::STR, "category", "The transaction category.\n"
726  "\"send\" Transactions sent.\n"
727  "\"receive\" Non-coinbase transactions received.\n"
728  "\"generate\" Coinbase transactions received with more than 100 confirmations.\n"
729  "\"immature\" Coinbase transactions received with 100 or fewer confirmations.\n"
730  "\"orphan\" Orphaned coinbase transactions received."},
731  {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT},
732  {RPCResult::Type::STR, "label", /*optional=*/true, "A comment for the address/transaction, if any"},
733  {RPCResult::Type::NUM, "vout", "the vout value"},
734  {RPCResult::Type::STR_AMOUNT, "fee", /*optional=*/true, "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
735  "'send' category of transactions."},
736  {RPCResult::Type::BOOL, "abandoned", /*optional=*/true, "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
737  "'send' category of transactions."},
738  }},
739  }},
740  {RPCResult::Type::STR_HEX, "hex", "Raw data for transaction"},
741  {RPCResult::Type::OBJ, "decoded", /*optional=*/true, "The decoded transaction (only present when `verbose` is passed)",
742  {
743  {RPCResult::Type::ELISION, "", "Equivalent to the RPC decoderawtransaction method, or the RPC getrawtransaction method when `verbose` is passed."},
744  }},
745  })
746  },
747  RPCExamples{
748  HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
749  + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
750  + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" false true")
751  + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
752  },
753  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
754 {
755  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
756  if (!pwallet) return NullUniValue;
757 
758  // Make sure the results are valid at least up to the most recent block
759  // the user could have gotten from another RPC command prior to now
760  pwallet->BlockUntilSyncedToCurrentChain();
761 
762  LOCK(pwallet->cs_wallet);
763 
764  uint256 hash(ParseHashV(request.params[0], "txid"));
765 
767 
768  if (ParseIncludeWatchonly(request.params[1], *pwallet)) {
769  filter |= ISMINE_WATCH_ONLY;
770  }
771 
772  bool verbose = request.params[2].isNull() ? false : request.params[2].get_bool();
773 
774  UniValue entry(UniValue::VOBJ);
775  auto it = pwallet->mapWallet.find(hash);
776  if (it == pwallet->mapWallet.end()) {
777  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
778  }
779  const CWalletTx& wtx = it->second;
780 
781  CAmount nCredit = CachedTxGetCredit(*pwallet, wtx, filter);
782  CAmount nDebit = CachedTxGetDebit(*pwallet, wtx, filter);
783  CAmount nNet = nCredit - nDebit;
784  CAmount nFee = (CachedTxIsFromMe(*pwallet, wtx, filter) ? wtx.tx->GetValueOut() - nDebit : 0);
785 
786  entry.pushKV("amount", ValueFromAmount(nNet - nFee));
787  if (CachedTxIsFromMe(*pwallet, wtx, filter))
788  entry.pushKV("fee", ValueFromAmount(nFee));
789 
790  WalletTxToJSON(*pwallet, wtx, entry);
791 
792  UniValue details(UniValue::VARR);
793  ListTransactions(*pwallet, wtx, 0, false, details, filter, nullptr /* filter_label */);
794  entry.pushKV("details", details);
795 
796  std::string strHex = EncodeHexTx(*wtx.tx, pwallet->chain().rpcSerializationFlags());
797  entry.pushKV("hex", strHex);
798 
799  if (verbose) {
800  UniValue decoded(UniValue::VOBJ);
801  TxToUniv(*wtx.tx, uint256(), decoded, false);
802  entry.pushKV("decoded", decoded);
803  }
804 
805  return entry;
806 },
807  };
808 }
809 
811 {
812  return RPCHelpMan{"abandontransaction",
813  "\nMark in-wallet transaction <txid> as abandoned\n"
814  "This will mark this transaction and all its in-wallet descendants as abandoned which will allow\n"
815  "for their inputs to be respent. It can be used to replace \"stuck\" or evicted transactions.\n"
816  "It only works on transactions which are not included in a block and are not currently in the mempool.\n"
817  "It has no effect on transactions which are already abandoned.\n",
818  {
819  {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
820  },
822  RPCExamples{
823  HelpExampleCli("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
824  + HelpExampleRpc("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
825  },
826  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
827 {
828  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
829  if (!pwallet) return NullUniValue;
830 
831  // Make sure the results are valid at least up to the most recent block
832  // the user could have gotten from another RPC command prior to now
833  pwallet->BlockUntilSyncedToCurrentChain();
834 
835  LOCK(pwallet->cs_wallet);
836 
837  uint256 hash(ParseHashV(request.params[0], "txid"));
838 
839  if (!pwallet->mapWallet.count(hash)) {
840  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
841  }
842  if (!pwallet->AbandonTransaction(hash)) {
843  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not eligible for abandonment");
844  }
845 
846  return NullUniValue;
847 },
848  };
849 }
850 
852 {
853  return RPCHelpMan{"rescanblockchain",
854  "\nRescan the local blockchain for wallet related transactions.\n"
855  "Note: Use \"getwalletinfo\" to query the scanning progress.\n",
856  {
857  {"start_height", RPCArg::Type::NUM, RPCArg::Default{0}, "block height where the rescan should start"},
858  {"stop_height", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "the last block height that should be scanned. If none is provided it will rescan up to the tip at return time of this call."},
859  },
860  RPCResult{
861  RPCResult::Type::OBJ, "", "",
862  {
863  {RPCResult::Type::NUM, "start_height", "The block height where the rescan started (the requested height or 0)"},
864  {RPCResult::Type::NUM, "stop_height", "The height of the last rescanned block. May be null in rare cases if there was a reorg and the call didn't scan any blocks because they were already scanned in the background."},
865  }
866  },
867  RPCExamples{
868  HelpExampleCli("rescanblockchain", "100000 120000")
869  + HelpExampleRpc("rescanblockchain", "100000, 120000")
870  },
871  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
872 {
873  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
874  if (!pwallet) return NullUniValue;
875  CWallet& wallet{*pwallet};
876 
877  // Make sure the results are valid at least up to the most recent block
878  // the user could have gotten from another RPC command prior to now
879  wallet.BlockUntilSyncedToCurrentChain();
880 
881  WalletRescanReserver reserver(*pwallet);
882  if (!reserver.reserve()) {
883  throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
884  }
885 
886  int start_height = 0;
887  std::optional<int> stop_height;
888  uint256 start_block;
889  {
890  LOCK(pwallet->cs_wallet);
891  int tip_height = pwallet->GetLastBlockHeight();
892 
893  if (!request.params[0].isNull()) {
894  start_height = request.params[0].get_int();
895  if (start_height < 0 || start_height > tip_height) {
896  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid start_height");
897  }
898  }
899 
900  if (!request.params[1].isNull()) {
901  stop_height = request.params[1].get_int();
902  if (*stop_height < 0 || *stop_height > tip_height) {
903  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid stop_height");
904  } else if (*stop_height < start_height) {
905  throw JSONRPCError(RPC_INVALID_PARAMETER, "stop_height must be greater than start_height");
906  }
907  }
908 
909  // We can't rescan beyond non-pruned blocks, stop and throw an error
910  if (!pwallet->chain().hasBlocks(pwallet->GetLastBlockHash(), start_height, stop_height)) {
911  throw JSONRPCError(RPC_MISC_ERROR, "Can't rescan beyond pruned data. Use RPC call getblockchaininfo to determine your pruned height.");
912  }
913 
914  CHECK_NONFATAL(pwallet->chain().findAncestorByHeight(pwallet->GetLastBlockHash(), start_height, FoundBlock().hash(start_block)));
915  }
916 
917  CWallet::ScanResult result =
918  pwallet->ScanForWalletTransactions(start_block, start_height, stop_height, reserver, true /* fUpdate */);
919  switch (result.status) {
921  break;
923  throw JSONRPCError(RPC_MISC_ERROR, "Rescan failed. Potentially corrupted data files.");
925  throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted.");
926  // no default case, so the compiler can warn about missing cases
927  }
928  UniValue response(UniValue::VOBJ);
929  response.pushKV("start_height", start_height);
930  response.pushKV("stop_height", result.last_scanned_height ? *result.last_scanned_height : UniValue());
931  return response;
932 },
933  };
934 }
935 
937 {
938  return RPCHelpMan{"abortrescan",
939  "\nStops current wallet rescan triggered by an RPC call, e.g. by an importprivkey call.\n"
940  "Note: Use \"getwalletinfo\" to query the scanning progress.\n",
941  {},
942  RPCResult{RPCResult::Type::BOOL, "", "Whether the abort was successful"},
943  RPCExamples{
944  "\nImport a private key\n"
945  + HelpExampleCli("importprivkey", "\"mykey\"") +
946  "\nAbort the running wallet rescan\n"
947  + HelpExampleCli("abortrescan", "") +
948  "\nAs a JSON-RPC call\n"
949  + HelpExampleRpc("abortrescan", "")
950  },
951  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
952 {
953  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
954  if (!pwallet) return NullUniValue;
955 
956  if (!pwallet->IsScanning() || pwallet->IsAbortingRescan()) return false;
957  pwallet->AbortRescan();
958  return true;
959 },
960  };
961 }
962 } // namespace wallet
RPC_MISC_ERROR
@ RPC_MISC_ERROR
General application defined errors.
Definition: protocol.h:39
wallet::listtransactions
RPCHelpMan listtransactions()
Definition: transactions.cpp:449
wallet::CWalletTx::GetHash
const uint256 & GetHash() const
Definition: transaction.h:298
RPCResult::Type::ELISION
@ ELISION
Special type to denote elision (...)
HelpExampleCli
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:156
wallet::ISMINE_WATCH_ONLY
@ ISMINE_WATCH_ONLY
Definition: ismine.h:43
UniValue::VOBJ
@ VOBJ
Definition: univalue.h:19
wallet::isminefilter
std::underlying_type< isminetype >::type isminefilter
used for bitflags of isminetype
Definition: wallet.h:40
RPC_INTERNAL_ERROR
@ RPC_INTERNAL_ERROR
Definition: protocol.h:35
wallet.h
CHECK_NONFATAL
#define CHECK_NONFATAL(condition)
Throw a NonFatalCheckError when the condition evaluates to false.
Definition: check.h:32
CBlockHeader::IsNull
bool IsNull() const
Definition: block.h:48
wallet::WalletRescanReserver
RAII object to check and reserve a wallet rescan.
Definition: wallet.h:902
wallet::tallyitem::fIsWatchonly
bool fIsWatchonly
Definition: transactions.cpp:64
key_io.h
RPCHelpMan
Definition: util.h:345
Cat
V Cat(V v1, V &&v2)
Concatenate two vectors, moving elements.
Definition: vector.h:31
NullUniValue
const UniValue NullUniValue
Definition: univalue.cpp:13
RBFTransactionState
RBFTransactionState
The rbf state of unconfirmed transactions.
Definition: rbf.h:20
RPC_INVALID_PARAMETER
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition: protocol.h:43
wallet::CWallet::ScanResult::FAILURE
@ FAILURE
Definition: wallet.h:524
wallet::MaybePushAddress
static void MaybePushAddress(UniValue &entry, const CTxDestination &dest)
Definition: transactions.cpp:326
ParseHashV
uint256 ParseHashV(const UniValue &v, std::string strName)
Utilities: convert hex-encoded Values (throws error if not hex).
Definition: util.cpp:90
RPCArg::Optional::NO
@ NO
Required arg.
wallet::listsinceblock
RPCHelpMan listsinceblock()
Definition: transactions.cpp:560
RPCArg::Type::STR
@ STR
wallet::rescanblockchain
RPCHelpMan rescanblockchain()
Definition: transactions.cpp:851
wallet::GetWalletForJSONRPCRequest
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: util.cpp:55
wallet::CWalletTx::GetTxTime
int64_t GetTxTime() const
Definition: transaction.cpp:22
RPCResult::Type::NUM
@ NUM
wallet
Definition: node.h:38
wallet::abortrescan
RPCHelpMan abortrescan()
Definition: transactions.cpp:936
UniValue::isNull
bool isNull() const
Definition: univalue.h:75
interfaces::Chain::findBlock
virtual bool findBlock(const uint256 &hash, const FoundBlock &block={})=0
Return whether node has the block and optionally return block metadata or contents.
CTransactionRef
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:386
wallet::CWalletTx
A transaction with a bunch of additional info that only the owner cares about.
Definition: transaction.h:137
core_io.h
UniValue::pushKV
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
ValueFromAmount
UniValue ValueFromAmount(const CAmount amount)
Definition: core_write.cpp:21
wallet::CWalletTx::mapValue
mapValue_t mapValue
Key/value map with information about the transaction.
Definition: transaction.h:165
UniValue
Definition: univalue.h:17
wallet::CachedTxIsTrusted
bool CachedTxIsTrusted(const CWallet &wallet, const CWalletTx &wtx, std::set< uint256 > &trusted_parents)
Definition: receive.cpp:279
wallet::CWalletTx::state
const T * state() const
Definition: transaction.h:291
RPCArg::Type::NUM
@ NUM
wallet::abandontransaction
RPCHelpMan abandontransaction()
Definition: transactions.cpp:810
CTxOut::nValue
CAmount nValue
Definition: transaction.h:131
UniValue::get_str
const std::string & get_str() const
Definition: univalue_get.cpp:98
wallet::listreceivedbyaddress
RPCHelpMan listreceivedbyaddress()
Definition: transactions.cpp:228
interfaces::Chain
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
Definition: chain.h:94
CURRENCY_UNIT
const std::string CURRENCY_UNIT
Definition: feerate.h:14
wallet::CachedTxIsFromMe
bool CachedTxIsFromMe(const CWallet &wallet, const CWalletTx &wtx, const isminefilter &filter)
Definition: receive.cpp:274
util.h
CTxDestination
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:157
wallet::CWallet::ScanResult
Definition: wallet.h:523
RPCArg::DefaultHint
std::string DefaultHint
Definition: util.h:155
IsValidDestination
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:332
RPCArg::Optional::OMITTED_NAMED_ARG
@ OMITTED_NAMED_ARG
Optional arg that is a named argument and has a default value of null.
wallet::CachedTxGetAmounts
void CachedTxGetAmounts(const CWallet &wallet, const CWalletTx &wtx, std::list< COutputEntry > &listReceived, std::list< COutputEntry > &listSent, CAmount &nFee, const isminefilter &filter)
Definition: receive.cpp:217
CTxOut
An output of a transaction.
Definition: transaction.h:128
RPCArg::Type::STR_HEX
@ STR_HEX
Special type that is a STR with only hex chars.
RPCResult::Type::OBJ
@ OBJ
RPCResult::Type::NONE
@ NONE
wallet::CWallet::ScanResult::SUCCESS
@ SUCCESS
Definition: wallet.h:524
wallet::CWallet
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:232
CTxOut::scriptPubKey
CScript scriptPubKey
Definition: transaction.h:132
wallet::tallyitem::nAmount
CAmount nAmount
Definition: transactions.cpp:61
RPCResult::Type::STR_HEX
@ STR_HEX
Special string with only hex chars.
CAmount
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
base_blob::GetHex
std::string GetHex() const
Definition: uint256.cpp:20
RPCExamples
Definition: util.h:335
RPC_WALLET_ERROR
@ RPC_WALLET_ERROR
Wallet errors.
Definition: protocol.h:71
interfaces::FoundBlock
Helper for findBlock to selectively return pieces of block data.
Definition: chain.h:43
RPCResult::Type::STR
@ STR
uint256
256-bit opaque blob.
Definition: uint256.h:124
RPCResult::Type::NUM_TIME
@ NUM_TIME
Special numeric to denote unix epoch time.
RPCResult::Type::ARR
@ ARR
wallet::CachedTxGetCredit
CAmount CachedTxGetCredit(const CWallet &wallet, const CWalletTx &wtx, const isminefilter &filter)
Definition: receive.cpp:124
wallet::tallyitem
Definition: transactions.cpp:59
wallet::gettransaction
RPCHelpMan gettransaction()
Definition: transactions.cpp:699
HelpExampleRpc
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:174
ExtractDestination
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:213
wallet::tallyitem::nConf
int nConf
Definition: transactions.cpp:62
CNoDestination
Definition: standard.h:73
interfaces::Chain::isRBFOptIn
virtual RBFTransactionState isRBFOptIn(const CTransaction &tx)=0
Check if transaction is RBF opt in.
wallet::ISMINE_SPENDABLE
@ ISMINE_SPENDABLE
Definition: ismine.h:44
EncodeHexTx
std::string EncodeHexTx(const CTransaction &tx, const int serializeFlags=0)
Definition: core_write.cpp:138
RPC_INVALID_ADDRESS_OR_KEY
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
Definition: protocol.h:41
CBlockHeader::hashPrevBlock
uint256 hashPrevBlock
Definition: block.h:25
CBlock
Definition: block.h:62
wallet::ListTransactions
static void ListTransactions(const CWallet &wallet, const CWalletTx &wtx, int nMinDepth, bool fLong, UniValue &ret, const isminefilter &filter_ismine, const std::string *filter_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
List transactions based on the given criteria.
Definition: transactions.cpp:344
wallet::ListReceived
static UniValue ListReceived(const CWallet &wallet, const UniValue &params, const bool by_label, const bool include_immature_coinbase) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
Definition: transactions.cpp:70
CBlock::vtx
std::vector< CTransactionRef > vtx
Definition: block.h:66
RPCResult::Type::BOOL
@ BOOL
EXCLUSIVE_LOCKS_REQUIRED
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:49
JSONRPCError
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:51
wallet::tallyitem::tallyitem
tallyitem()
Definition: transactions.cpp:65
vector.h
LOCK
#define LOCK(cs)
Definition: sync.h:226
wallet::CWallet::ScanResult::last_scanned_height
std::optional< int > last_scanned_height
Definition: wallet.h:530
RPCArg::Type::BOOL
@ BOOL
DecodeDestination
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
Definition: key_io.cpp:281
UniValue::push_back
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
wallet::TransactionDescriptionString
static const std::vector< RPCResult > TransactionDescriptionString()
Definition: transactions.cpp:422
wallet::WalletRescanReserver::reserve
bool reserve()
Definition: wallet.h:910
EXAMPLE_ADDRESS
const std::string EXAMPLE_ADDRESS[2]
Example bech32 addresses for the RPCExamples help documentation.
Definition: util.cpp:22
IsValidDestinationString
bool IsValidDestinationString(const std::string &str, const CChainParams &params)
Definition: key_io.cpp:292
wallet::CWallet::ScanResult::USER_ABORT
@ USER_ABORT
Definition: wallet.h:524
UniValue::getValues
const std::vector< UniValue > & getValues() const
Definition: univalue_get.cpp:84
wallet::WalletTxToJSON
static void WalletTxToJSON(const CWallet &wallet, const CWalletTx &wtx, UniValue &entry)
Definition: transactions.cpp:17
RBFTransactionState::UNKNOWN
@ UNKNOWN
Unconfirmed tx that does not signal rbf and is not in the mempool.
receive.h
UniValue::size
size_t size() const
Definition: univalue.h:66
wallet::CachedTxGetDebit
CAmount CachedTxGetDebit(const CWallet &wallet, const CWalletTx &wtx, const isminefilter &filter)
filter decides which addresses will count towards the debit
Definition: receive.cpp:141
wallet::CWalletTx::nTimeReceived
unsigned int nTimeReceived
time received by this node
Definition: transaction.h:168
wallet::CWallet::ScanResult::status
enum wallet::CWallet::ScanResult::@17 status
JSONRPCRequest
Definition: request.h:28
TxToUniv
void TxToUniv(const CTransaction &tx, const uint256 &hashBlock, UniValue &entry, bool include_hex=true, int serialize_flags=0, const CTxUndo *txundo=nullptr, TxVerbosity verbosity=TxVerbosity::SHOW_DETAILS)
Definition: core_write.cpp:166
RPCResult
Definition: util.h:231
wallet::CWallet::TxItems
std::multimap< int64_t, CWalletTx * > TxItems
Definition: wallet.h:394
wallet::listreceivedbylabel
RPCHelpMan listreceivedbylabel()
Definition: transactions.cpp:281
wallet::TxStateConfirmed
State of transaction confirmed in a block.
Definition: transaction.h:24
RPCResult::Type::STR_AMOUNT
@ STR_AMOUNT
Special string to represent a floating point amount.
UniValue::VARR
@ VARR
Definition: univalue.h:19
wallet::tallyitem::txids
std::vector< uint256 > txids
Definition: transactions.cpp:63
wallet::COutputEntry
Definition: receive.h:38
RBFTransactionState::REPLACEABLE_BIP125
@ REPLACEABLE_BIP125
Either this tx or a mempool ancestor signals rbf.
EncodeDestination
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:276
UNIX_EPOCH_TIME
const std::string UNIX_EPOCH_TIME
String used to describe UNIX epoch time in documentation, factored out to a constant for consistency.
Definition: util.cpp:21
wallet::ParseIncludeWatchonly
bool ParseIncludeWatchonly(const UniValue &include_watchonly, const CWallet &wallet)
Used by RPC commands that have an include_watchonly parameter.
Definition: util.cpp:34
wallet::CWalletTx::IsCoinBase
bool IsCoinBase() const
Definition: transaction.h:299
wallet::CWalletTx::tx
CTransactionRef tx
Definition: transaction.h:219
rbf.h