Bitcoin ABC  0.24.7
P2P Digital Currency
transactiondesc.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2016 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #ifdef HAVE_CONFIG_H
6 #include <config/bitcoin-config.h>
7 #endif
8 
9 #include <qt/transactiondesc.h>
10 
11 #include <cashaddrenc.h>
12 #include <chain.h>
13 #include <consensus/consensus.h>
14 #include <interfaces/node.h>
15 #include <interfaces/wallet.h>
16 #include <key_io.h>
17 #include <policy/policy.h>
18 #include <qt/bitcoinunits.h>
19 #include <qt/guiutil.h>
20 #include <qt/paymentserver.h>
21 #include <qt/transactionrecord.h>
22 #include <script/script.h>
23 #include <util/system.h>
24 #include <validation.h>
25 #include <wallet/ismine.h>
26 
27 #include <cstdint>
28 #include <string>
29 
30 QString
32  const interfaces::WalletTxStatus &status,
33  bool inMempool, int numBlocks) {
34  if (!status.is_final) {
35  if (wtx.tx->nLockTime < LOCKTIME_THRESHOLD) {
36  return tr("Open for %n more block(s)", "",
37  wtx.tx->nLockTime - numBlocks);
38  } else {
39  return tr("Open until %1")
40  .arg(GUIUtil::dateTimeStr(wtx.tx->nLockTime));
41  }
42  } else {
43  int nDepth = status.depth_in_main_chain;
44  if (nDepth < 0) {
45  return tr("conflicted with a transaction with %1 confirmations")
46  .arg(-nDepth);
47  } else if (nDepth == 0) {
48  return tr("0/unconfirmed, %1")
49  .arg((inMempool ? tr("in memory pool")
50  : tr("not in memory pool"))) +
51  (status.is_abandoned ? ", " + tr("abandoned") : "");
52  } else if (nDepth < 6) {
53  return tr("%1/unconfirmed").arg(nDepth);
54  } else {
55  return tr("%1 confirmations").arg(nDepth);
56  }
57  }
58 }
59 
60 #ifndef ENABLE_BIP70
61 // Takes an encoded PaymentRequest as a string and tries to find the Common Name
62 // of the X.509 certificate used to sign the PaymentRequest.
63 bool GetPaymentRequestMerchant(const std::string &pr, QString &merchant) {
64  // Search for the supported pki type strings
65  if (pr.find(std::string({0x12, 0x0b}) + "x509+sha256") !=
66  std::string::npos ||
67  pr.find(std::string({0x12, 0x09}) + "x509+sha1") != std::string::npos) {
68  // We want the common name of the Subject of the cert. This should be
69  // the second occurrence of the bytes 0x0603550403. The first occurrence
70  // of those is the common name of the issuer. After those bytes will be
71  // either 0x13 or 0x0C, then length, then either the ascii or utf8
72  // string with the common name which is the merchant name
73  size_t cn_pos = pr.find({0x06, 0x03, 0x55, 0x04, 0x03});
74  if (cn_pos != std::string::npos) {
75  cn_pos = pr.find({0x06, 0x03, 0x55, 0x04, 0x03}, cn_pos + 5);
76  if (cn_pos != std::string::npos) {
77  cn_pos += 5;
78  if (pr[cn_pos] == 0x13 || pr[cn_pos] == 0x0c) {
79  cn_pos++; // Consume the type
80  int str_len = pr[cn_pos];
81  cn_pos++; // Consume the string length
82  merchant = QString::fromUtf8(pr.data() + cn_pos, str_len);
83  return true;
84  }
85  }
86  }
87  }
88  return false;
89 }
90 #endif
91 
93  interfaces::Wallet &wallet,
94  TransactionRecord *rec, int unit) {
95  int numBlocks;
98  bool inMempool;
100  rec->txid, status, orderForm, inMempool, numBlocks);
101 
102  QString strHTML;
103 
104  strHTML.reserve(4000);
105  strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
106 
107  int64_t nTime = wtx.time;
108  Amount nCredit = wtx.credit;
109  Amount nDebit = wtx.debit;
110  Amount nNet = nCredit - nDebit;
111 
112  strHTML += "<b>" + tr("Status") + ":</b> " +
113  FormatTxStatus(wtx, status, inMempool, numBlocks);
114  strHTML += "<br>";
115 
116  strHTML += "<b>" + tr("Date") + ":</b> " +
117  (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>";
118 
119  //
120  // From
121  //
122  if (wtx.is_coinbase) {
123  strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>";
124  } else if (wtx.value_map.count("from") && !wtx.value_map["from"].empty()) {
125  // Online transaction
126  strHTML += "<b>" + tr("From") + ":</b> " +
127  GUIUtil::HtmlEscape(wtx.value_map["from"]) + "<br>";
128  } else {
129  // Offline transaction
130  if (nNet > Amount::zero()) {
131  // Credit
132  CTxDestination address =
133  DecodeDestination(rec->address, wallet.getChainParams());
134  if (IsValidDestination(address)) {
135  std::string name;
136  isminetype ismine;
137  if (wallet.getAddress(address, &name, &ismine,
138  /* purpose= */ nullptr)) {
139  strHTML +=
140  "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>";
141  strHTML += "<b>" + tr("To") + ":</b> ";
142  strHTML += GUIUtil::HtmlEscape(rec->address);
143  QString addressOwned = ismine == ISMINE_SPENDABLE
144  ? tr("own address")
145  : tr("watch-only");
146  if (!name.empty()) {
147  strHTML += " (" + addressOwned + ", " + tr("label") +
148  ": " + GUIUtil::HtmlEscape(name) + ")";
149  } else {
150  strHTML += " (" + addressOwned + ")";
151  }
152  strHTML += "<br>";
153  }
154  }
155  }
156  }
157 
158  //
159  // To
160  //
161  if (wtx.value_map.count("to") && !wtx.value_map["to"].empty()) {
162  // Online transaction
163  std::string strAddress = wtx.value_map["to"];
164  strHTML += "<b>" + tr("To") + ":</b> ";
165  CTxDestination dest =
166  DecodeDestination(strAddress, wallet.getChainParams());
167  std::string name;
168  if (wallet.getAddress(dest, &name, /* is_mine= */ nullptr,
169  /* purpose= */ nullptr) &&
170  !name.empty()) {
171  strHTML += GUIUtil::HtmlEscape(name) + " ";
172  }
173  strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
174  }
175 
176  //
177  // Amount
178  //
179  if (wtx.is_coinbase && nCredit == Amount::zero()) {
180  //
181  // Coinbase
182  //
183  Amount nUnmatured = Amount::zero();
184  for (const CTxOut &txout : wtx.tx->vout) {
185  nUnmatured += wallet.getCredit(txout, ISMINE_ALL);
186  }
187  strHTML += "<b>" + tr("Credit") + ":</b> ";
188  if (status.is_in_main_chain) {
189  strHTML += BitcoinUnits::formatHtmlWithUnit(unit, nUnmatured) +
190  " (" +
191  tr("matures in %n more block(s)", "",
192  status.blocks_to_maturity) +
193  ")";
194  } else {
195  strHTML += "(" + tr("not accepted") + ")";
196  }
197  strHTML += "<br>";
198  } else if (nNet > Amount::zero()) {
199  //
200  // Credit
201  //
202  strHTML += "<b>" + tr("Credit") + ":</b> " +
203  BitcoinUnits::formatHtmlWithUnit(unit, nNet) + "<br>";
204  } else {
205  isminetype fAllFromMe = ISMINE_SPENDABLE;
206  for (const isminetype mine : wtx.txin_is_mine) {
207  if (fAllFromMe > mine) {
208  fAllFromMe = mine;
209  }
210  }
211 
212  isminetype fAllToMe = ISMINE_SPENDABLE;
213  for (const isminetype mine : wtx.txout_is_mine) {
214  if (fAllToMe > mine) {
215  fAllToMe = mine;
216  }
217  }
218 
219  if (fAllFromMe) {
220  if (fAllFromMe & ISMINE_WATCH_ONLY) {
221  strHTML +=
222  "<b>" + tr("From") + ":</b> " + tr("watch-only") + "<br>";
223  }
224 
225  //
226  // Debit
227  //
228  auto mine = wtx.txout_is_mine.begin();
229  for (const CTxOut &txout : wtx.tx->vout) {
230  // Ignore change
231  isminetype toSelf = *(mine++);
232  if ((toSelf == ISMINE_SPENDABLE) &&
233  (fAllFromMe == ISMINE_SPENDABLE)) {
234  continue;
235  }
236 
237  if (!wtx.value_map.count("to") || wtx.value_map["to"].empty()) {
238  // Offline transaction
239  CTxDestination address;
240  if (ExtractDestination(txout.scriptPubKey, address)) {
241  strHTML += "<b>" + tr("To") + ":</b> ";
242  std::string name;
243  if (wallet.getAddress(address, &name,
244  /* is_mine= */ nullptr,
245  /* purpose= */ nullptr) &&
246  !name.empty()) {
247  strHTML += GUIUtil::HtmlEscape(name) + " ";
248  }
249  strHTML += GUIUtil::HtmlEscape(
250  EncodeCashAddr(address, wallet.getChainParams()));
251  if (toSelf == ISMINE_SPENDABLE) {
252  strHTML += " (own address)";
253  } else if (toSelf & ISMINE_WATCH_ONLY) {
254  strHTML += " (watch-only)";
255  }
256  strHTML += "<br>";
257  }
258  }
259 
260  strHTML +=
261  "<b>" + tr("Debit") + ":</b> " +
262  BitcoinUnits::formatHtmlWithUnit(unit, -1 * txout.nValue) +
263  "<br>";
264  if (toSelf) {
265  strHTML +=
266  "<b>" + tr("Credit") + ":</b> " +
268  "<br>";
269  }
270  }
271 
272  if (fAllToMe) {
273  // Payment to self
274  Amount nChange = wtx.change;
275  Amount nValue = nCredit - nChange;
276  strHTML += "<b>" + tr("Total debit") + ":</b> " +
277  BitcoinUnits::formatHtmlWithUnit(unit, -1 * nValue) +
278  "<br>";
279  strHTML += "<b>" + tr("Total credit") + ":</b> " +
280  BitcoinUnits::formatHtmlWithUnit(unit, nValue) +
281  "<br>";
282  }
283 
284  Amount nTxFee = nDebit - wtx.tx->GetValueOut();
285  if (nTxFee > Amount::zero()) {
286  strHTML += "<b>" + tr("Transaction fee") + ":</b> " +
287  BitcoinUnits::formatHtmlWithUnit(unit, -1 * nTxFee) +
288  "<br>";
289  }
290  } else {
291  //
292  // Mixed debit transaction
293  //
294  auto mine = wtx.txin_is_mine.begin();
295  for (const CTxIn &txin : wtx.tx->vin) {
296  if (*(mine++)) {
297  strHTML += "<b>" + tr("Debit") + ":</b> " +
299  unit, -wallet.getDebit(txin, ISMINE_ALL)) +
300  "<br>";
301  }
302  }
303  mine = wtx.txout_is_mine.begin();
304  for (const CTxOut &txout : wtx.tx->vout) {
305  if (*(mine++)) {
306  strHTML += "<b>" + tr("Credit") + ":</b> " +
308  unit, wallet.getCredit(txout, ISMINE_ALL)) +
309  "<br>";
310  }
311  }
312  }
313  }
314 
315  strHTML += "<b>" + tr("Net amount") + ":</b> " +
316  BitcoinUnits::formatHtmlWithUnit(unit, nNet, true) + "<br>";
317 
318  //
319  // Message
320  //
321  if (wtx.value_map.count("message") && !wtx.value_map["message"].empty()) {
322  strHTML += "<br><b>" + tr("Message") + ":</b><br>" +
323  GUIUtil::HtmlEscape(wtx.value_map["message"], true) + "<br>";
324  }
325  if (wtx.value_map.count("comment") && !wtx.value_map["comment"].empty()) {
326  strHTML += "<br><b>" + tr("Comment") + ":</b><br>" +
327  GUIUtil::HtmlEscape(wtx.value_map["comment"], true) + "<br>";
328  }
329  strHTML +=
330  "<b>" + tr("Transaction ID") + ":</b> " + rec->getTxID() + "<br>";
331  strHTML += "<b>" + tr("Transaction total size") + ":</b> " +
332  QString::number(wtx.tx->GetTotalSize()) + " bytes<br>";
333  strHTML += "<b>" + tr("Output index") + ":</b> " +
334  QString::number(rec->getOutputIndex()) + "<br>";
335 
336  // Message from normal bitcoincash:URI (bitcoincash:123...?message=example)
337  for (const std::pair<std::string, std::string> &r : orderForm) {
338  if (r.first == "Message") {
339  strHTML += "<br><b>" + tr("Message") + ":</b><br>" +
340  GUIUtil::HtmlEscape(r.second, true) + "<br>";
341  }
342 
343  //
344  // PaymentRequest info:
345  //
346  if (r.first == "PaymentRequest") {
347  QString merchant;
348 #ifdef ENABLE_BIP70
349  PaymentRequestPlus req;
350  req.parse(
351  QByteArray::fromRawData(r.second.data(), r.second.size()));
352  if (!req.getMerchant(PaymentServer::getCertStore(), merchant)) {
353  merchant.clear();
354  }
355 #else
356  if (!GetPaymentRequestMerchant(r.second, merchant)) {
357  merchant.clear();
358  } else {
359  merchant += tr(" (Certificate was not verified)");
360  }
361 #endif
362  if (!merchant.isNull()) {
363  strHTML += "<b>" + tr("Merchant") + ":</b> " +
364  GUIUtil::HtmlEscape(merchant) + "<br>";
365  }
366  }
367  }
368 
369  if (wtx.is_coinbase) {
370  quint32 numBlocksToMaturity = COINBASE_MATURITY + 1;
371  strHTML +=
372  "<br>" +
373  tr("Generated coins must mature %1 blocks before they can be "
374  "spent. When you generated this block, it was broadcast to the "
375  "network to be added to the block chain. If it fails to get "
376  "into the chain, its state will change to \"not accepted\" and "
377  "it won't be spendable. This may occasionally happen if another "
378  "node generates a block within a few seconds of yours.")
379  .arg(QString::number(numBlocksToMaturity)) +
380  "<br>";
381  }
382 
383  //
384  // Debug view
385  //
386  if (gArgs.GetBoolArg("-debug", false)) {
387  strHTML += "<hr><br>" + tr("Debug information") + "<br><br>";
388  for (const CTxIn &txin : wtx.tx->vin) {
389  if (wallet.txinIsMine(txin)) {
390  strHTML += "<b>" + tr("Debit") + ":</b> " +
392  unit, -wallet.getDebit(txin, ISMINE_ALL)) +
393  "<br>";
394  }
395  }
396  for (const CTxOut &txout : wtx.tx->vout) {
397  if (wallet.txoutIsMine(txout)) {
398  strHTML += "<b>" + tr("Credit") + ":</b> " +
400  unit, wallet.getCredit(txout, ISMINE_ALL)) +
401  "<br>";
402  }
403  }
404 
405  strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
406  strHTML += GUIUtil::HtmlEscape(wtx.tx->ToString(), true);
407 
408  strHTML += "<br><b>" + tr("Inputs") + ":</b>";
409  strHTML += "<ul>";
410 
411  for (const CTxIn &txin : wtx.tx->vin) {
412  COutPoint prevout = txin.prevout;
413 
414  Coin prev;
415  if (node.getUnspentOutput(prevout, prev)) {
416  strHTML += "<li>";
417  const CTxOut &vout = prev.GetTxOut();
418  CTxDestination address;
419  if (ExtractDestination(vout.scriptPubKey, address)) {
420  std::string name;
421  if (wallet.getAddress(address, &name,
422  /* is_mine= */ nullptr,
423  /* purpose= */ nullptr) &&
424  !name.empty()) {
425  strHTML += GUIUtil::HtmlEscape(name) + " ";
426  }
427  strHTML += QString::fromStdString(
428  EncodeCashAddr(address, wallet.getChainParams()));
429  }
430  strHTML = strHTML + " " + tr("Amount") + "=" +
432  strHTML = strHTML + " IsMine=" +
433  (wallet.txoutIsMine(vout) & ISMINE_SPENDABLE
434  ? tr("true")
435  : tr("false")) +
436  "</li>";
437  strHTML = strHTML + " IsWatchOnly=" +
438  (wallet.txoutIsMine(vout) & ISMINE_WATCH_ONLY
439  ? tr("true")
440  : tr("false")) +
441  "</li>";
442  }
443  }
444 
445  strHTML += "</ul>";
446  }
447 
448  strHTML += "</font></html>";
449  return strHTML;
450 }
BitcoinUnits::formatHtmlWithUnit
static QString formatHtmlWithUnit(int unit, const Amount amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD)
Format as HTML string (with unit)
Definition: bitcoinunits.cpp:167
TransactionRecord::txid
TxId txid
Definition: transactionrecord.h:128
CTxIn
An input of a transaction.
Definition: transaction.h:61
policy.h
interfaces::Wallet::txoutIsMine
virtual isminetype txoutIsMine(const CTxOut &txout)=0
Return whether transaction output belongs to wallet.
CTxOut::nValue
Amount nValue
Definition: transaction.h:132
ArgsManager::GetBoolArg
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: system.cpp:517
interfaces::Wallet::getDebit
virtual Amount getDebit(const CTxIn &txin, isminefilter filter)=0
Return debit amount if transaction input belongs to wallet.
LOCKTIME_THRESHOLD
static const unsigned int LOCKTIME_THRESHOLD
Definition: script.h:39
interfaces::WalletTx::change
Amount change
Definition: wallet.h:380
interfaces::WalletTxStatus::depth_in_main_chain
int depth_in_main_chain
Definition: wallet.h:390
COINBASE_MATURITY
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule).
Definition: consensus.h:32
interfaces::Wallet::getWalletTxDetails
virtual WalletTx getWalletTxDetails(const TxId &txid, WalletTxStatus &tx_status, WalletOrderForm &order_form, bool &in_mempool, int &num_blocks)=0
Get transaction details.
key_io.h
ISMINE_ALL
@ ISMINE_ALL
Definition: ismine.h:23
transactiondesc.h
ISMINE_WATCH_ONLY
@ ISMINE_WATCH_ONLY
Definition: ismine.h:20
interfaces::WalletTxStatus::is_final
bool is_final
Definition: wallet.h:393
interfaces::WalletTx::is_coinbase
bool is_coinbase
Definition: wallet.h:383
GetPaymentRequestMerchant
bool GetPaymentRequestMerchant(const std::string &pr, QString &merchant)
Definition: transactiondesc.cpp:63
interfaces::Wallet::getChainParams
virtual const CChainParams & getChainParams()=0
Get chainparams.
node.h
interfaces::Node::getUnspentOutput
virtual bool getUnspentOutput(const COutPoint &output, Coin &coin)=0
Get unspent outputs associated with a transaction.
PaymentRequestPlus::parse
bool parse(const QByteArray &data)
Definition: paymentrequestplus.cpp:26
interfaces::WalletTx::time
int64_t time
Definition: wallet.h:381
interfaces::WalletTx::credit
Amount credit
Definition: wallet.h:378
TransactionDesc::toHTML
static QString toHTML(interfaces::Node &node, interfaces::Wallet &wallet, TransactionRecord *rec, int unit)
Definition: transactiondesc.cpp:92
TransactionRecord
UI model for a transaction.
Definition: transactionrecord.h:91
interfaces::Wallet::getAddress
virtual bool getAddress(const CTxDestination &dest, std::string *name, isminetype *is_mine, std::string *purpose)=0
Look up address in wallet, return whether exists.
Amount::zero
static constexpr Amount zero()
Definition: amount.h:42
ismine.h
interfaces::WalletTx::value_map
std::map< std::string, std::string > value_map
Definition: wallet.h:382
isminetype
isminetype
IsMine() return codes.
Definition: ismine.h:18
PaymentRequestPlus
Definition: paymentrequestplus.h:28
IsValidDestination
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:263
CTxOut
An output of a transaction.
Definition: transaction.h:130
Coin
A UTXO entry.
Definition: coins.h:27
EncodeCashAddr
std::string EncodeCashAddr(const CTxDestination &dst, const CChainParams &params)
Definition: cashaddrenc.cpp:91
CTxOut::scriptPubKey
CScript scriptPubKey
Definition: transaction.h:133
interfaces::Wallet::txinIsMine
virtual isminetype txinIsMine(const CTxIn &txin)=0
Return whether transaction input belongs to wallet.
consensus.h
interfaces::WalletTx
Definition: wallet.h:372
TransactionDesc::FormatTxStatus
static QString FormatTxStatus(const interfaces::WalletTx &wtx, const interfaces::WalletTxStatus &status, bool inMempool, int numBlocks)
Definition: transactiondesc.cpp:31
guiutil.h
interfaces::WalletTxStatus
Updated transaction status.
Definition: wallet.h:387
interfaces::Wallet
Interface for accessing a wallet.
Definition: wallet.h:59
Amount
Definition: amount.h:19
interfaces::WalletTxStatus::is_in_main_chain
bool is_in_main_chain
Definition: wallet.h:397
interfaces::WalletTxStatus::blocks_to_maturity
int blocks_to_maturity
Definition: wallet.h:389
ExtractDestination
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:161
interfaces::WalletOrderForm
std::vector< std::pair< std::string, std::string > > WalletOrderForm
Definition: wallet.h:55
interfaces::Node
Top-level interface for a bitcoin node (bitcoind process).
Definition: node.h:55
interfaces::WalletTx::txin_is_mine
std::vector< isminetype > txin_is_mine
Definition: wallet.h:374
name
const char * name
Definition: rest.cpp:43
transactionrecord.h
ISMINE_SPENDABLE
@ ISMINE_SPENDABLE
Definition: ismine.h:21
system.h
TransactionRecord::address
std::string address
Definition: transactionrecord.h:131
interfaces::Wallet::getCredit
virtual Amount getCredit(const CTxOut &txout, isminefilter filter)=0
Return credit amount if transaction input belongs to wallet.
interfaces::WalletTx::txout_is_mine
std::vector< isminetype > txout_is_mine
Definition: wallet.h:375
GUIUtil::HtmlEscape
QString HtmlEscape(const QString &str, bool fMultiLine)
Definition: guiutil.cpp:240
gArgs
ArgsManager gArgs
Definition: system.cpp:75
CTxIn::prevout
COutPoint prevout
Definition: transaction.h:63
TransactionRecord::getOutputIndex
int getOutputIndex() const
Return the output index of the subtransaction
Definition: transactionrecord.cpp:224
interfaces::WalletTxStatus::is_abandoned
bool is_abandoned
Definition: wallet.h:395
bitcoinunits.h
interfaces::WalletTx::debit
Amount debit
Definition: wallet.h:379
wallet.h
PaymentRequestPlus::getMerchant
bool getMerchant(X509_STORE *certStore, QString &merchant) const
Definition: paymentrequestplus.cpp:59
script.h
GUIUtil::dateTimeStr
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:67
COutPoint
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:22
TransactionRecord::getTxID
QString getTxID() const
Return the unique identifier for this transaction (part)
Definition: transactionrecord.cpp:220
DecodeDestination
CTxDestination DecodeDestination(const std::string &addr, const CChainParams &params)
Definition: key_io.cpp:177
Coin::GetTxOut
CTxOut & GetTxOut()
Definition: coins.h:48
interfaces::WalletTx::tx
CTransactionRef tx
Definition: wallet.h:373
CTxDestination
boost::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:132
cashaddrenc.h
paymentserver.h