Bitcoin Core  27.99.0
P2P Digital Currency
spend.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2022 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 <consensus/validation.h>
6 #include <core_io.h>
7 #include <key_io.h>
8 #include <policy/policy.h>
10 #include <rpc/util.h>
11 #include <script/script.h>
12 #include <util/fees.h>
13 #include <util/rbf.h>
14 #include <util/translation.h>
15 #include <util/vector.h>
16 #include <wallet/coincontrol.h>
17 #include <wallet/feebumper.h>
18 #include <wallet/fees.h>
19 #include <wallet/rpc/util.h>
20 #include <wallet/spend.h>
21 #include <wallet/wallet.h>
22 
23 #include <univalue.h>
24 
25 
26 namespace wallet {
27 std::vector<CRecipient> CreateRecipients(const std::vector<std::pair<CTxDestination, CAmount>>& outputs, const std::set<int>& subtract_fee_outputs)
28 {
29  std::vector<CRecipient> recipients;
30  for (size_t i = 0; i < outputs.size(); ++i) {
31  const auto& [destination, amount] = outputs.at(i);
32  CRecipient recipient{destination, amount, subtract_fee_outputs.contains(i)};
33  recipients.push_back(recipient);
34  }
35  return recipients;
36 }
37 
38 static void InterpretFeeEstimationInstructions(const UniValue& conf_target, const UniValue& estimate_mode, const UniValue& fee_rate, UniValue& options)
39 {
40  if (options.exists("conf_target") || options.exists("estimate_mode")) {
41  if (!conf_target.isNull() || !estimate_mode.isNull()) {
42  throw JSONRPCError(RPC_INVALID_PARAMETER, "Pass conf_target and estimate_mode either as arguments or in the options object, but not both");
43  }
44  } else {
45  options.pushKV("conf_target", conf_target);
46  options.pushKV("estimate_mode", estimate_mode);
47  }
48  if (options.exists("fee_rate")) {
49  if (!fee_rate.isNull()) {
50  throw JSONRPCError(RPC_INVALID_PARAMETER, "Pass the fee_rate either as an argument, or in the options object, but not both");
51  }
52  } else {
53  options.pushKV("fee_rate", fee_rate);
54  }
55  if (!options["conf_target"].isNull() && (options["estimate_mode"].isNull() || (options["estimate_mode"].get_str() == "unset"))) {
56  throw JSONRPCError(RPC_INVALID_PARAMETER, "Specify estimate_mode");
57  }
58 }
59 
60 std::set<int> InterpretSubtractFeeFromOutputInstructions(const UniValue& sffo_instructions, const std::vector<std::string>& destinations)
61 {
62  std::set<int> sffo_set;
63  if (sffo_instructions.isNull()) return sffo_set;
64  if (sffo_instructions.isBool()) {
65  if (sffo_instructions.get_bool()) sffo_set.insert(0);
66  return sffo_set;
67  }
68  for (const auto& sffo : sffo_instructions.getValues()) {
69  if (sffo.isStr()) {
70  for (size_t i = 0; i < destinations.size(); ++i) {
71  if (sffo.get_str() == destinations.at(i)) {
72  sffo_set.insert(i);
73  break;
74  }
75  }
76  }
77  if (sffo.isNum()) {
78  int pos = sffo.getInt<int>();
79  if (sffo_set.contains(pos))
80  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, duplicated position: %d", pos));
81  if (pos < 0)
82  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, negative position: %d", pos));
83  if (pos >= int(destinations.size()))
84  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, position too large: %d", pos));
85  sffo_set.insert(pos);
86  }
87  }
88  return sffo_set;
89 }
90 
91 static UniValue FinishTransaction(const std::shared_ptr<CWallet> pwallet, const UniValue& options, const CMutableTransaction& rawTx)
92 {
93  // Make a blank psbt
94  PartiallySignedTransaction psbtx(rawTx);
95 
96  // First fill transaction with our data without signing,
97  // so external signers are not asked to sign more than once.
98  bool complete;
99  pwallet->FillPSBT(psbtx, complete, SIGHASH_DEFAULT, /*sign=*/false, /*bip32derivs=*/true);
100  const TransactionError err{pwallet->FillPSBT(psbtx, complete, SIGHASH_DEFAULT, /*sign=*/true, /*bip32derivs=*/false)};
101  if (err != TransactionError::OK) {
102  throw JSONRPCTransactionError(err);
103  }
104 
106  complete = FinalizeAndExtractPSBT(psbtx, mtx);
107 
108  UniValue result(UniValue::VOBJ);
109 
110  const bool psbt_opt_in{options.exists("psbt") && options["psbt"].get_bool()};
111  bool add_to_wallet{options.exists("add_to_wallet") ? options["add_to_wallet"].get_bool() : true};
112  if (psbt_opt_in || !complete || !add_to_wallet) {
113  // Serialize the PSBT
114  DataStream ssTx{};
115  ssTx << psbtx;
116  result.pushKV("psbt", EncodeBase64(ssTx.str()));
117  }
118 
119  if (complete) {
120  std::string hex{EncodeHexTx(CTransaction(mtx))};
121  CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
122  result.pushKV("txid", tx->GetHash().GetHex());
123  if (add_to_wallet && !psbt_opt_in) {
124  pwallet->CommitTransaction(tx, {}, /*orderForm=*/{});
125  } else {
126  result.pushKV("hex", hex);
127  }
128  }
129  result.pushKV("complete", complete);
130 
131  return result;
132 }
133 
134 static void PreventOutdatedOptions(const UniValue& options)
135 {
136  if (options.exists("feeRate")) {
137  throw JSONRPCError(RPC_INVALID_PARAMETER, "Use fee_rate (" + CURRENCY_ATOM + "/vB) instead of feeRate");
138  }
139  if (options.exists("changeAddress")) {
140  throw JSONRPCError(RPC_INVALID_PARAMETER, "Use change_address instead of changeAddress");
141  }
142  if (options.exists("changePosition")) {
143  throw JSONRPCError(RPC_INVALID_PARAMETER, "Use change_position instead of changePosition");
144  }
145  if (options.exists("includeWatching")) {
146  throw JSONRPCError(RPC_INVALID_PARAMETER, "Use include_watching instead of includeWatching");
147  }
148  if (options.exists("lockUnspents")) {
149  throw JSONRPCError(RPC_INVALID_PARAMETER, "Use lock_unspents instead of lockUnspents");
150  }
151  if (options.exists("subtractFeeFromOutputs")) {
152  throw JSONRPCError(RPC_INVALID_PARAMETER, "Use subtract_fee_from_outputs instead of subtractFeeFromOutputs");
153  }
154 }
155 
156 UniValue SendMoney(CWallet& wallet, const CCoinControl &coin_control, std::vector<CRecipient> &recipients, mapValue_t map_value, bool verbose)
157 {
159 
160  // This function is only used by sendtoaddress and sendmany.
161  // This should always try to sign, if we don't have private keys, don't try to do anything here.
162  if (wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
163  throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
164  }
165 
166  // Shuffle recipient list
167  std::shuffle(recipients.begin(), recipients.end(), FastRandomContext());
168 
169  // Send
170  auto res = CreateTransaction(wallet, recipients, /*change_pos=*/std::nullopt, coin_control, true);
171  if (!res) {
173  }
174  const CTransactionRef& tx = res->tx;
175  wallet.CommitTransaction(tx, std::move(map_value), /*orderForm=*/{});
176  if (verbose) {
177  UniValue entry(UniValue::VOBJ);
178  entry.pushKV("txid", tx->GetHash().GetHex());
179  entry.pushKV("fee_reason", StringForFeeReason(res->fee_calc.reason));
180  return entry;
181  }
182  return tx->GetHash().GetHex();
183 }
184 
185 
199 static void SetFeeEstimateMode(const CWallet& wallet, CCoinControl& cc, const UniValue& conf_target, const UniValue& estimate_mode, const UniValue& fee_rate, bool override_min_fee)
200 {
201  if (!fee_rate.isNull()) {
202  if (!conf_target.isNull()) {
203  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.");
204  }
205  if (!estimate_mode.isNull() && estimate_mode.get_str() != "unset") {
206  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both estimate_mode and fee_rate");
207  }
208  // Fee rates in sat/vB cannot represent more than 3 significant digits.
209  cc.m_feerate = CFeeRate{AmountFromValue(fee_rate, /*decimals=*/3)};
210  if (override_min_fee) cc.fOverrideFeeRate = true;
211  // Default RBF to true for explicit fee_rate, if unset.
212  if (!cc.m_signal_bip125_rbf) cc.m_signal_bip125_rbf = true;
213  return;
214  }
215  if (!estimate_mode.isNull() && !FeeModeFromString(estimate_mode.get_str(), cc.m_fee_mode)) {
217  }
218  if (!conf_target.isNull()) {
219  cc.m_confirm_target = ParseConfirmTarget(conf_target, wallet.chain().estimateMaxBlocks());
220  }
221 }
222 
224 {
225  return RPCHelpMan{"sendtoaddress",
226  "\nSend an amount to a given address." +
228  {
229  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to send to."},
230  {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The amount in " + CURRENCY_UNIT + " to send. eg 0.1"},
231  {"comment", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A comment used to store what the transaction is for.\n"
232  "This is not part of the transaction, just kept in your wallet."},
233  {"comment_to", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A comment to store the name of the person or organization\n"
234  "to which you're sending the transaction. This is not part of the \n"
235  "transaction, just kept in your wallet."},
236  {"subtractfeefromamount", RPCArg::Type::BOOL, RPCArg::Default{false}, "The fee will be deducted from the amount being sent.\n"
237  "The recipient will receive less bitcoins than you enter in the amount field."},
238  {"replaceable", RPCArg::Type::BOOL, RPCArg::DefaultHint{"wallet default"}, "Signal that this transaction can be replaced by a transaction (BIP 125)"},
239  {"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"},
240  {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n"
241  "\"" + FeeModes("\"\n\"") + "\""},
242  {"avoid_reuse", RPCArg::Type::BOOL, RPCArg::Default{true}, "(only available if avoid_reuse wallet flag is set) Avoid spending from dirty addresses; addresses are considered\n"
243  "dirty if they have previously been used in a transaction. If true, this also activates avoidpartialspends, grouping outputs by their addresses."},
244  {"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
245  {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "If true, return extra information about the transaction."},
246  },
247  {
248  RPCResult{"if verbose is not set or set to false",
249  RPCResult::Type::STR_HEX, "txid", "The transaction id."
250  },
251  RPCResult{"if verbose is set to true",
252  RPCResult::Type::OBJ, "", "",
253  {
254  {RPCResult::Type::STR_HEX, "txid", "The transaction id."},
255  {RPCResult::Type::STR, "fee_reason", "The transaction fee reason."}
256  },
257  },
258  },
259  RPCExamples{
260  "\nSend 0.1 BTC\n"
261  + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1") +
262  "\nSend 0.1 BTC with a confirmation target of 6 blocks in economical fee estimate mode using positional arguments\n"
263  + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"donation\" \"sean's outpost\" false true 6 economical") +
264  "\nSend 0.1 BTC with a fee rate of 1.1 " + CURRENCY_ATOM + "/vB, subtract fee from amount, BIP125-replaceable, using positional arguments\n"
265  + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"drinks\" \"room77\" true true null \"unset\" null 1.1") +
266  "\nSend 0.2 BTC with a confirmation target of 6 blocks in economical fee estimate mode using named arguments\n"
267  + HelpExampleCli("-named sendtoaddress", "address=\"" + EXAMPLE_ADDRESS[0] + "\" amount=0.2 conf_target=6 estimate_mode=\"economical\"") +
268  "\nSend 0.5 BTC with a fee rate of 25 " + CURRENCY_ATOM + "/vB using named arguments\n"
269  + HelpExampleCli("-named sendtoaddress", "address=\"" + EXAMPLE_ADDRESS[0] + "\" amount=0.5 fee_rate=25")
270  + HelpExampleCli("-named sendtoaddress", "address=\"" + EXAMPLE_ADDRESS[0] + "\" amount=0.5 fee_rate=25 subtractfeefromamount=false replaceable=true avoid_reuse=true comment=\"2 pizzas\" comment_to=\"jeremy\" verbose=true")
271  },
272  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
273 {
274  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
275  if (!pwallet) return UniValue::VNULL;
276 
277  // Make sure the results are valid at least up to the most recent block
278  // the user could have gotten from another RPC command prior to now
279  pwallet->BlockUntilSyncedToCurrentChain();
280 
281  LOCK(pwallet->cs_wallet);
282 
283  // Wallet comments
284  mapValue_t mapValue;
285  if (!request.params[2].isNull() && !request.params[2].get_str().empty())
286  mapValue["comment"] = request.params[2].get_str();
287  if (!request.params[3].isNull() && !request.params[3].get_str().empty())
288  mapValue["to"] = request.params[3].get_str();
289 
290  CCoinControl coin_control;
291  if (!request.params[5].isNull()) {
292  coin_control.m_signal_bip125_rbf = request.params[5].get_bool();
293  }
294 
295  coin_control.m_avoid_address_reuse = GetAvoidReuseFlag(*pwallet, request.params[8]);
296  // We also enable partial spend avoidance if reuse avoidance is set.
297  coin_control.m_avoid_partial_spends |= coin_control.m_avoid_address_reuse;
298 
299  SetFeeEstimateMode(*pwallet, coin_control, /*conf_target=*/request.params[6], /*estimate_mode=*/request.params[7], /*fee_rate=*/request.params[9], /*override_min_fee=*/false);
300 
301  EnsureWalletIsUnlocked(*pwallet);
302 
303  UniValue address_amounts(UniValue::VOBJ);
304  const std::string address = request.params[0].get_str();
305  address_amounts.pushKV(address, request.params[1]);
306  std::vector<CRecipient> recipients = CreateRecipients(
307  ParseOutputs(address_amounts),
308  InterpretSubtractFeeFromOutputInstructions(request.params[4], address_amounts.getKeys())
309  );
310  const bool verbose{request.params[10].isNull() ? false : request.params[10].get_bool()};
311 
312  return SendMoney(*pwallet, coin_control, recipients, mapValue, verbose);
313 },
314  };
315 }
316 
318 {
319  return RPCHelpMan{"sendmany",
320  "Send multiple times. Amounts are double-precision floating point numbers." +
322  {
323  {"dummy", RPCArg::Type::STR, RPCArg::Default{"\"\""}, "Must be set to \"\" for backwards compatibility.",
325  .oneline_description = "\"\"",
326  }},
327  {"amounts", RPCArg::Type::OBJ_USER_KEYS, RPCArg::Optional::NO, "The addresses and amounts",
328  {
329  {"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The bitcoin address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value"},
330  },
331  },
332  {"minconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "Ignored dummy value"},
333  {"comment", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A comment"},
334  {"subtractfeefrom", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "The addresses.\n"
335  "The fee will be equally deducted from the amount of each selected address.\n"
336  "Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
337  "If no addresses are specified here, the sender pays the fee.",
338  {
339  {"address", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Subtract fee from this address"},
340  },
341  },
342  {"replaceable", RPCArg::Type::BOOL, RPCArg::DefaultHint{"wallet default"}, "Signal that this transaction can be replaced by a transaction (BIP 125)"},
343  {"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"},
344  {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n"
345  "\"" + FeeModes("\"\n\"") + "\""},
346  {"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
347  {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "If true, return extra information about the transaction."},
348  },
349  {
350  RPCResult{"if verbose is not set or set to false",
351  RPCResult::Type::STR_HEX, "txid", "The transaction id for the send. Only 1 transaction is created regardless of\n"
352  "the number of addresses."
353  },
354  RPCResult{"if verbose is set to true",
355  RPCResult::Type::OBJ, "", "",
356  {
357  {RPCResult::Type::STR_HEX, "txid", "The transaction id for the send. Only 1 transaction is created regardless of\n"
358  "the number of addresses."},
359  {RPCResult::Type::STR, "fee_reason", "The transaction fee reason."}
360  },
361  },
362  },
363  RPCExamples{
364  "\nSend two amounts to two different addresses:\n"
365  + HelpExampleCli("sendmany", "\"\" \"{\\\"" + EXAMPLE_ADDRESS[0] + "\\\":0.01,\\\"" + EXAMPLE_ADDRESS[1] + "\\\":0.02}\"") +
366  "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
367  + HelpExampleCli("sendmany", "\"\" \"{\\\"" + EXAMPLE_ADDRESS[0] + "\\\":0.01,\\\"" + EXAMPLE_ADDRESS[1] + "\\\":0.02}\" 6 \"testing\"") +
368  "\nSend two amounts to two different addresses, subtract fee from amount:\n"
369  + HelpExampleCli("sendmany", "\"\" \"{\\\"" + EXAMPLE_ADDRESS[0] + "\\\":0.01,\\\"" + EXAMPLE_ADDRESS[1] + "\\\":0.02}\" 1 \"\" \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"") +
370  "\nAs a JSON-RPC call\n"
371  + HelpExampleRpc("sendmany", "\"\", {\"" + EXAMPLE_ADDRESS[0] + "\":0.01,\"" + EXAMPLE_ADDRESS[1] + "\":0.02}, 6, \"testing\"")
372  },
373  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
374 {
375  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
376  if (!pwallet) return UniValue::VNULL;
377 
378  // Make sure the results are valid at least up to the most recent block
379  // the user could have gotten from another RPC command prior to now
380  pwallet->BlockUntilSyncedToCurrentChain();
381 
382  LOCK(pwallet->cs_wallet);
383 
384  if (!request.params[0].isNull() && !request.params[0].get_str().empty()) {
385  throw JSONRPCError(RPC_INVALID_PARAMETER, "Dummy value must be set to \"\"");
386  }
387  UniValue sendTo = request.params[1].get_obj();
388 
389  mapValue_t mapValue;
390  if (!request.params[3].isNull() && !request.params[3].get_str().empty())
391  mapValue["comment"] = request.params[3].get_str();
392 
393  CCoinControl coin_control;
394  if (!request.params[5].isNull()) {
395  coin_control.m_signal_bip125_rbf = request.params[5].get_bool();
396  }
397 
398  SetFeeEstimateMode(*pwallet, coin_control, /*conf_target=*/request.params[6], /*estimate_mode=*/request.params[7], /*fee_rate=*/request.params[8], /*override_min_fee=*/false);
399 
400  std::vector<CRecipient> recipients = CreateRecipients(
401  ParseOutputs(sendTo),
402  InterpretSubtractFeeFromOutputInstructions(request.params[4], sendTo.getKeys())
403  );
404  const bool verbose{request.params[9].isNull() ? false : request.params[9].get_bool()};
405 
406  return SendMoney(*pwallet, coin_control, recipients, std::move(mapValue), verbose);
407 },
408  };
409 }
410 
412 {
413  return RPCHelpMan{"settxfee",
414  "\nSet the transaction fee rate in " + CURRENCY_UNIT + "/kvB for this wallet. Overrides the global -paytxfee command line parameter.\n"
415  "Can be deactivated by passing 0 as the fee. In that case automatic fee selection will be used by default.\n",
416  {
417  {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The transaction fee rate in " + CURRENCY_UNIT + "/kvB"},
418  },
419  RPCResult{
420  RPCResult::Type::BOOL, "", "Returns true if successful"
421  },
422  RPCExamples{
423  HelpExampleCli("settxfee", "0.00001")
424  + HelpExampleRpc("settxfee", "0.00001")
425  },
426  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
427 {
428  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
429  if (!pwallet) return UniValue::VNULL;
430 
431  LOCK(pwallet->cs_wallet);
432 
433  CAmount nAmount = AmountFromValue(request.params[0]);
434  CFeeRate tx_fee_rate(nAmount, 1000);
435  CFeeRate max_tx_fee_rate(pwallet->m_default_max_tx_fee, 1000);
436  if (tx_fee_rate == CFeeRate(0)) {
437  // automatic selection
438  } else if (tx_fee_rate < pwallet->chain().relayMinFee()) {
439  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be less than min relay tx fee (%s)", pwallet->chain().relayMinFee().ToString()));
440  } else if (tx_fee_rate < pwallet->m_min_fee) {
441  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be less than wallet min fee (%s)", pwallet->m_min_fee.ToString()));
442  } else if (tx_fee_rate > max_tx_fee_rate) {
443  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be more than wallet max tx fee (%s)", max_tx_fee_rate.ToString()));
444  }
445 
446  pwallet->m_pay_tx_fee = tx_fee_rate;
447  return true;
448 },
449  };
450 }
451 
452 
453 // Only includes key documentation where the key is snake_case in all RPC methods. MixedCase keys can be added later.
454 static std::vector<RPCArg> FundTxDoc(bool solving_data = true)
455 {
456  std::vector<RPCArg> args = {
457  {"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks", RPCArgOptions{.also_positional = true}},
458  {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n"
459  "\"" + FeeModes("\"\n\"") + "\"", RPCArgOptions{.also_positional = true}},
460  {
461  "replaceable", RPCArg::Type::BOOL, RPCArg::DefaultHint{"wallet default"}, "Marks this transaction as BIP125-replaceable.\n"
462  "Allows this transaction to be replaced by a transaction with higher fees"
463  },
464  };
465  if (solving_data) {
466  args.push_back({"solving_data", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "Keys and scripts needed for producing a final transaction with a dummy signature.\n"
467  "Used for fee estimation during coin selection.",
468  {
469  {
470  "pubkeys", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "Public keys involved in this transaction.",
471  {
472  {"pubkey", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A public key"},
473  }
474  },
475  {
476  "scripts", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "Scripts involved in this transaction.",
477  {
478  {"script", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A script"},
479  }
480  },
481  {
482  "descriptors", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "Descriptors that provide solving data for this transaction.",
483  {
484  {"descriptor", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A descriptor"},
485  }
486  },
487  }
488  });
489  }
490  return args;
491 }
492 
493 CreatedTransactionResult FundTransaction(CWallet& wallet, const CMutableTransaction& tx, const std::vector<CRecipient>& recipients, const UniValue& options, CCoinControl& coinControl, bool override_min_fee)
494 {
495  // We want to make sure tx.vout is not used now that we are passing outputs as a vector of recipients.
496  // This sets us up to remove tx completely in a future PR in favor of passing the inputs directly.
497  CHECK_NONFATAL(tx.vout.empty());
498  // Make sure the results are valid at least up to the most recent block
499  // the user could have gotten from another RPC command prior to now
500  wallet.BlockUntilSyncedToCurrentChain();
501 
502  std::optional<unsigned int> change_position;
503  bool lockUnspents = false;
504  if (!options.isNull()) {
505  if (options.type() == UniValue::VBOOL) {
506  // backward compatibility bool only fallback
507  coinControl.fAllowWatchOnly = options.get_bool();
508  }
509  else {
510  RPCTypeCheckObj(options,
511  {
512  {"add_inputs", UniValueType(UniValue::VBOOL)},
513  {"include_unsafe", UniValueType(UniValue::VBOOL)},
514  {"add_to_wallet", UniValueType(UniValue::VBOOL)},
515  {"changeAddress", UniValueType(UniValue::VSTR)},
516  {"change_address", UniValueType(UniValue::VSTR)},
517  {"changePosition", UniValueType(UniValue::VNUM)},
518  {"change_position", UniValueType(UniValue::VNUM)},
519  {"change_type", UniValueType(UniValue::VSTR)},
520  {"includeWatching", UniValueType(UniValue::VBOOL)},
521  {"include_watching", UniValueType(UniValue::VBOOL)},
522  {"inputs", UniValueType(UniValue::VARR)},
523  {"lockUnspents", UniValueType(UniValue::VBOOL)},
524  {"lock_unspents", UniValueType(UniValue::VBOOL)},
525  {"locktime", UniValueType(UniValue::VNUM)},
526  {"fee_rate", UniValueType()}, // will be checked by AmountFromValue() in SetFeeEstimateMode()
527  {"feeRate", UniValueType()}, // will be checked by AmountFromValue() below
528  {"psbt", UniValueType(UniValue::VBOOL)},
529  {"solving_data", UniValueType(UniValue::VOBJ)},
530  {"subtractFeeFromOutputs", UniValueType(UniValue::VARR)},
531  {"subtract_fee_from_outputs", UniValueType(UniValue::VARR)},
532  {"replaceable", UniValueType(UniValue::VBOOL)},
533  {"conf_target", UniValueType(UniValue::VNUM)},
534  {"estimate_mode", UniValueType(UniValue::VSTR)},
535  {"minconf", UniValueType(UniValue::VNUM)},
536  {"maxconf", UniValueType(UniValue::VNUM)},
537  {"input_weights", UniValueType(UniValue::VARR)},
538  },
539  true, true);
540 
541  if (options.exists("add_inputs")) {
542  coinControl.m_allow_other_inputs = options["add_inputs"].get_bool();
543  }
544 
545  if (options.exists("changeAddress") || options.exists("change_address")) {
546  const std::string change_address_str = (options.exists("change_address") ? options["change_address"] : options["changeAddress"]).get_str();
547  CTxDestination dest = DecodeDestination(change_address_str);
548 
549  if (!IsValidDestination(dest)) {
550  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Change address must be a valid bitcoin address");
551  }
552 
553  coinControl.destChange = dest;
554  }
555 
556  if (options.exists("changePosition") || options.exists("change_position")) {
557  int pos = (options.exists("change_position") ? options["change_position"] : options["changePosition"]).getInt<int>();
558  if (pos < 0 || (unsigned int)pos > recipients.size()) {
559  throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds");
560  }
561  change_position = (unsigned int)pos;
562  }
563 
564  if (options.exists("change_type")) {
565  if (options.exists("changeAddress") || options.exists("change_address")) {
566  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both change address and address type options");
567  }
568  if (std::optional<OutputType> parsed = ParseOutputType(options["change_type"].get_str())) {
569  coinControl.m_change_type.emplace(parsed.value());
570  } else {
571  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown change type '%s'", options["change_type"].get_str()));
572  }
573  }
574 
575  const UniValue include_watching_option = options.exists("include_watching") ? options["include_watching"] : options["includeWatching"];
576  coinControl.fAllowWatchOnly = ParseIncludeWatchonly(include_watching_option, wallet);
577 
578  if (options.exists("lockUnspents") || options.exists("lock_unspents")) {
579  lockUnspents = (options.exists("lock_unspents") ? options["lock_unspents"] : options["lockUnspents"]).get_bool();
580  }
581 
582  if (options.exists("include_unsafe")) {
583  coinControl.m_include_unsafe_inputs = options["include_unsafe"].get_bool();
584  }
585 
586  if (options.exists("feeRate")) {
587  if (options.exists("fee_rate")) {
588  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both fee_rate (" + CURRENCY_ATOM + "/vB) and feeRate (" + CURRENCY_UNIT + "/kvB)");
589  }
590  if (options.exists("conf_target")) {
591  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and feeRate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.");
592  }
593  if (options.exists("estimate_mode")) {
594  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both estimate_mode and feeRate");
595  }
596  coinControl.m_feerate = CFeeRate(AmountFromValue(options["feeRate"]));
597  coinControl.fOverrideFeeRate = true;
598  }
599 
600  if (options.exists("replaceable")) {
601  coinControl.m_signal_bip125_rbf = options["replaceable"].get_bool();
602  }
603 
604  if (options.exists("minconf")) {
605  coinControl.m_min_depth = options["minconf"].getInt<int>();
606 
607  if (coinControl.m_min_depth < 0) {
608  throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative minconf");
609  }
610  }
611 
612  if (options.exists("maxconf")) {
613  coinControl.m_max_depth = options["maxconf"].getInt<int>();
614 
615  if (coinControl.m_max_depth < coinControl.m_min_depth) {
616  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("maxconf can't be lower than minconf: %d < %d", coinControl.m_max_depth, coinControl.m_min_depth));
617  }
618  }
619  SetFeeEstimateMode(wallet, coinControl, options["conf_target"], options["estimate_mode"], options["fee_rate"], override_min_fee);
620  }
621  } else {
622  // if options is null and not a bool
624  }
625 
626  if (options.exists("solving_data")) {
627  const UniValue solving_data = options["solving_data"].get_obj();
628  if (solving_data.exists("pubkeys")) {
629  for (const UniValue& pk_univ : solving_data["pubkeys"].get_array().getValues()) {
630  const std::string& pk_str = pk_univ.get_str();
631  if (!IsHex(pk_str)) {
632  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("'%s' is not hex", pk_str));
633  }
634  const std::vector<unsigned char> data(ParseHex(pk_str));
635  const CPubKey pubkey(data.begin(), data.end());
636  if (!pubkey.IsFullyValid()) {
637  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("'%s' is not a valid public key", pk_str));
638  }
639  coinControl.m_external_provider.pubkeys.emplace(pubkey.GetID(), pubkey);
640  // Add witness script for pubkeys
641  const CScript wit_script = GetScriptForDestination(WitnessV0KeyHash(pubkey));
642  coinControl.m_external_provider.scripts.emplace(CScriptID(wit_script), wit_script);
643  }
644  }
645 
646  if (solving_data.exists("scripts")) {
647  for (const UniValue& script_univ : solving_data["scripts"].get_array().getValues()) {
648  const std::string& script_str = script_univ.get_str();
649  if (!IsHex(script_str)) {
650  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("'%s' is not hex", script_str));
651  }
652  std::vector<unsigned char> script_data(ParseHex(script_str));
653  const CScript script(script_data.begin(), script_data.end());
654  coinControl.m_external_provider.scripts.emplace(CScriptID(script), script);
655  }
656  }
657 
658  if (solving_data.exists("descriptors")) {
659  for (const UniValue& desc_univ : solving_data["descriptors"].get_array().getValues()) {
660  const std::string& desc_str = desc_univ.get_str();
661  FlatSigningProvider desc_out;
662  std::string error;
663  std::vector<CScript> scripts_temp;
664  std::unique_ptr<Descriptor> desc = Parse(desc_str, desc_out, error, true);
665  if (!desc) {
666  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Unable to parse descriptor '%s': %s", desc_str, error));
667  }
668  desc->Expand(0, desc_out, scripts_temp, desc_out);
669  coinControl.m_external_provider.Merge(std::move(desc_out));
670  }
671  }
672  }
673 
674  if (options.exists("input_weights")) {
675  for (const UniValue& input : options["input_weights"].get_array().getValues()) {
676  Txid txid = Txid::FromUint256(ParseHashO(input, "txid"));
677 
678  const UniValue& vout_v = input.find_value("vout");
679  if (!vout_v.isNum()) {
680  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
681  }
682  int vout = vout_v.getInt<int>();
683  if (vout < 0) {
684  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout cannot be negative");
685  }
686 
687  const UniValue& weight_v = input.find_value("weight");
688  if (!weight_v.isNum()) {
689  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing weight key");
690  }
691  int64_t weight = weight_v.getInt<int64_t>();
692  const int64_t min_input_weight = GetTransactionInputWeight(CTxIn());
693  CHECK_NONFATAL(min_input_weight == 165);
694  if (weight < min_input_weight) {
695  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, weight cannot be less than 165 (41 bytes (size of outpoint + sequence + empty scriptSig) * 4 (witness scaling factor)) + 1 (empty witness)");
696  }
697  if (weight > MAX_STANDARD_TX_WEIGHT) {
698  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, weight cannot be greater than the maximum standard tx weight of %d", MAX_STANDARD_TX_WEIGHT));
699  }
700 
701  coinControl.SetInputWeight(COutPoint(txid, vout), weight);
702  }
703  }
704 
705  if (recipients.empty())
706  throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output");
707 
708  auto txr = FundTransaction(wallet, tx, recipients, change_position, lockUnspents, coinControl);
709  if (!txr) {
710  throw JSONRPCError(RPC_WALLET_ERROR, ErrorString(txr).original);
711  }
712  return *txr;
713 }
714 
715 static void SetOptionsInputWeights(const UniValue& inputs, UniValue& options)
716 {
717  if (options.exists("input_weights")) {
718  throw JSONRPCError(RPC_INVALID_PARAMETER, "Input weights should be specified in inputs rather than in options.");
719  }
720  if (inputs.size() == 0) {
721  return;
722  }
723  UniValue weights(UniValue::VARR);
724  for (const UniValue& input : inputs.getValues()) {
725  if (input.exists("weight")) {
726  weights.push_back(input);
727  }
728  }
729  options.pushKV("input_weights", weights);
730 }
731 
733 {
734  return RPCHelpMan{"fundrawtransaction",
735  "\nIf the transaction has no inputs, they will be automatically selected to meet its out value.\n"
736  "It will add at most one change output to the outputs.\n"
737  "No existing outputs will be modified unless \"subtractFeeFromOutputs\" is specified.\n"
738  "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
739  "The inputs added will not be signed, use signrawtransactionwithkey\n"
740  "or signrawtransactionwithwallet for that.\n"
741  "All existing inputs must either have their previous output transaction be in the wallet\n"
742  "or be in the UTXO set. Solving data must be provided for non-wallet inputs.\n"
743  "Note that all inputs selected must be of standard form and P2SH scripts must be\n"
744  "in the wallet using importaddress or addmultisigaddress (to calculate fees).\n"
745  "You can see whether this is the case by checking the \"solvable\" field in the listunspent output.\n"
746  "Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n",
747  {
748  {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex string of the raw transaction"},
749  {"options", RPCArg::Type::OBJ_NAMED_PARAMS, RPCArg::Optional::OMITTED, "For backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}",
750  Cat<std::vector<RPCArg>>(
751  {
752  {"add_inputs", RPCArg::Type::BOOL, RPCArg::Default{true}, "For a transaction with existing inputs, automatically include more if they are not enough."},
753  {"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include inputs that are not safe to spend (unconfirmed transactions from outside keys and unconfirmed replacement transactions).\n"
754  "Warning: the resulting transaction may become invalid if one of the unsafe inputs disappears.\n"
755  "If that happens, you will need to fund the transaction with different inputs and republish it."},
756  {"minconf", RPCArg::Type::NUM, RPCArg::Default{0}, "If add_inputs is specified, require inputs with at least this many confirmations."},
757  {"maxconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "If add_inputs is specified, require inputs with at most this many confirmations."},
758  {"changeAddress", RPCArg::Type::STR, RPCArg::DefaultHint{"automatic"}, "The bitcoin address to receive the change"},
759  {"changePosition", RPCArg::Type::NUM, RPCArg::DefaultHint{"random"}, "The index of the change output"},
760  {"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
761  {"includeWatching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch only.\n"
762  "Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
763  "e.g. with 'importpubkey' or 'importmulti' with the 'pubkeys' or 'desc' field."},
764  {"lockUnspents", RPCArg::Type::BOOL, RPCArg::Default{false}, "Lock selected unspent outputs"},
765  {"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
766  {"feeRate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_UNIT + "/kvB."},
767  {"subtractFeeFromOutputs", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "The integers.\n"
768  "The fee will be equally deducted from the amount of each specified output.\n"
769  "Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
770  "If no outputs are specified here, the sender pays the fee.",
771  {
772  {"vout_index", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "The zero-based output index, before a change output is added."},
773  },
774  },
775  {"input_weights", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "Inputs and their corresponding weights",
776  {
778  {
779  {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
780  {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output index"},
781  {"weight", RPCArg::Type::NUM, RPCArg::Optional::NO, "The maximum weight for this input, "
782  "including the weight of the outpoint and sequence number. "
783  "Note that serialized signature sizes are not guaranteed to be consistent, "
784  "so the maximum DER signatures size of 73 bytes should be used when considering ECDSA signatures."
785  "Remember to convert serialized sizes to weight units when necessary."},
786  },
787  },
788  },
789  },
790  },
791  FundTxDoc()),
793  .skip_type_check = true,
794  .oneline_description = "options",
795  }},
796  {"iswitness", RPCArg::Type::BOOL, RPCArg::DefaultHint{"depends on heuristic tests"}, "Whether the transaction hex is a serialized witness transaction.\n"
797  "If iswitness is not present, heuristic tests will be used in decoding.\n"
798  "If true, only witness deserialization will be tried.\n"
799  "If false, only non-witness deserialization will be tried.\n"
800  "This boolean should reflect whether the transaction has inputs\n"
801  "(e.g. fully valid, or on-chain transactions), if known by the caller."
802  },
803  },
804  RPCResult{
805  RPCResult::Type::OBJ, "", "",
806  {
807  {RPCResult::Type::STR_HEX, "hex", "The resulting raw transaction (hex-encoded string)"},
808  {RPCResult::Type::STR_AMOUNT, "fee", "Fee in " + CURRENCY_UNIT + " the resulting transaction pays"},
809  {RPCResult::Type::NUM, "changepos", "The position of the added change output, or -1"},
810  }
811  },
812  RPCExamples{
813  "\nCreate a transaction with no inputs\n"
814  + HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") +
815  "\nAdd sufficient unsigned inputs to meet the output value\n"
816  + HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") +
817  "\nSign the transaction\n"
818  + HelpExampleCli("signrawtransactionwithwallet", "\"fundedtransactionhex\"") +
819  "\nSend the transaction\n"
820  + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
821  },
822  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
823 {
824  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
825  if (!pwallet) return UniValue::VNULL;
826 
827  // parse hex string from parameter
829  bool try_witness = request.params[2].isNull() ? true : request.params[2].get_bool();
830  bool try_no_witness = request.params[2].isNull() ? true : !request.params[2].get_bool();
831  if (!DecodeHexTx(tx, request.params[0].get_str(), try_no_witness, try_witness)) {
832  throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
833  }
834  UniValue options = request.params[1];
835  std::vector<std::pair<CTxDestination, CAmount>> destinations;
836  for (const auto& tx_out : tx.vout) {
837  CTxDestination dest;
838  ExtractDestination(tx_out.scriptPubKey, dest);
839  destinations.emplace_back(dest, tx_out.nValue);
840  }
841  std::vector<std::string> dummy(destinations.size(), "dummy");
842  std::vector<CRecipient> recipients = CreateRecipients(
843  destinations,
844  InterpretSubtractFeeFromOutputInstructions(options["subtractFeeFromOutputs"], dummy)
845  );
846  CCoinControl coin_control;
847  // Automatically select (additional) coins. Can be overridden by options.add_inputs.
848  coin_control.m_allow_other_inputs = true;
849  // Clear tx.vout since it is not meant to be used now that we are passing outputs directly.
850  // This sets us up for a future PR to completely remove tx from the function signature in favor of passing inputs directly
851  tx.vout.clear();
852  auto txr = FundTransaction(*pwallet, tx, recipients, options, coin_control, /*override_min_fee=*/true);
853 
854  UniValue result(UniValue::VOBJ);
855  result.pushKV("hex", EncodeHexTx(*txr.tx));
856  result.pushKV("fee", ValueFromAmount(txr.fee));
857  result.pushKV("changepos", txr.change_pos ? (int)*txr.change_pos : -1);
858 
859  return result;
860 },
861  };
862 }
863 
865 {
866  return RPCHelpMan{"signrawtransactionwithwallet",
867  "\nSign inputs for raw transaction (serialized, hex-encoded).\n"
868  "The second optional argument (may be null) is an array of previous transaction outputs that\n"
869  "this transaction depends on but may not yet be in the block chain." +
871  {
872  {"hexstring", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction hex string"},
873  {"prevtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "The previous dependent transaction outputs",
874  {
876  {
877  {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
878  {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
879  {"scriptPubKey", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "script key"},
880  {"redeemScript", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "(required for P2SH) redeem script"},
881  {"witnessScript", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "(required for P2WSH or P2SH-P2WSH) witness script"},
882  {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::OMITTED, "(required for Segwit inputs) the amount spent"},
883  },
884  },
885  },
886  },
887  {"sighashtype", RPCArg::Type::STR, RPCArg::Default{"DEFAULT for Taproot, ALL otherwise"}, "The signature hash type. Must be one of\n"
888  " \"DEFAULT\"\n"
889  " \"ALL\"\n"
890  " \"NONE\"\n"
891  " \"SINGLE\"\n"
892  " \"ALL|ANYONECANPAY\"\n"
893  " \"NONE|ANYONECANPAY\"\n"
894  " \"SINGLE|ANYONECANPAY\""},
895  },
896  RPCResult{
897  RPCResult::Type::OBJ, "", "",
898  {
899  {RPCResult::Type::STR_HEX, "hex", "The hex-encoded raw transaction with signature(s)"},
900  {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
901  {RPCResult::Type::ARR, "errors", /*optional=*/true, "Script verification errors (if there are any)",
902  {
903  {RPCResult::Type::OBJ, "", "",
904  {
905  {RPCResult::Type::STR_HEX, "txid", "The hash of the referenced, previous transaction"},
906  {RPCResult::Type::NUM, "vout", "The index of the output to spent and used as input"},
907  {RPCResult::Type::ARR, "witness", "",
908  {
909  {RPCResult::Type::STR_HEX, "witness", ""},
910  }},
911  {RPCResult::Type::STR_HEX, "scriptSig", "The hex-encoded signature script"},
912  {RPCResult::Type::NUM, "sequence", "Script sequence number"},
913  {RPCResult::Type::STR, "error", "Verification or signing error related to the input"},
914  }},
915  }},
916  }
917  },
918  RPCExamples{
919  HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"")
920  + HelpExampleRpc("signrawtransactionwithwallet", "\"myhex\"")
921  },
922  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
923 {
924  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
925  if (!pwallet) return UniValue::VNULL;
926 
928  if (!DecodeHexTx(mtx, request.params[0].get_str())) {
929  throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input.");
930  }
931 
932  // Sign the transaction
933  LOCK(pwallet->cs_wallet);
934  EnsureWalletIsUnlocked(*pwallet);
935 
936  // Fetch previous transactions (inputs):
937  std::map<COutPoint, Coin> coins;
938  for (const CTxIn& txin : mtx.vin) {
939  coins[txin.prevout]; // Create empty map entry keyed by prevout.
940  }
941  pwallet->chain().findCoins(coins);
942 
943  // Parse the prevtxs array
944  ParsePrevouts(request.params[1], nullptr, coins);
945 
946  int nHashType = ParseSighashString(request.params[2]);
947 
948  // Script verification errors
949  std::map<int, bilingual_str> input_errors;
950 
951  bool complete = pwallet->SignTransaction(mtx, coins, nHashType, input_errors);
952  UniValue result(UniValue::VOBJ);
953  SignTransactionResultToJSON(mtx, complete, coins, input_errors, result);
954  return result;
955 },
956  };
957 }
958 
959 // Definition of allowed formats of specifying transaction outputs in
960 // `bumpfee`, `psbtbumpfee`, `send` and `walletcreatefundedpsbt` RPCs.
961 static std::vector<RPCArg> OutputsDoc()
962 {
963  return
964  {
966  {
967  {"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "A key-value pair. The key (string) is the bitcoin address,\n"
968  "the value (float or string) is the amount in " + CURRENCY_UNIT + ""},
969  },
970  },
972  {
973  {"data", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A key-value pair. The key must be \"data\", the value is hex-encoded data"},
974  },
975  },
976  };
977 }
978 
979 static RPCHelpMan bumpfee_helper(std::string method_name)
980 {
981  const bool want_psbt = method_name == "psbtbumpfee";
982  const std::string incremental_fee{CFeeRate(DEFAULT_INCREMENTAL_RELAY_FEE).ToString(FeeEstimateMode::SAT_VB)};
983 
984  return RPCHelpMan{method_name,
985  "\nBumps the fee of an opt-in-RBF transaction T, replacing it with a new transaction B.\n"
986  + std::string(want_psbt ? "Returns a PSBT instead of creating and signing a new transaction.\n" : "") +
987  "An opt-in RBF transaction with the given txid must be in the wallet.\n"
988  "The command will pay the additional fee by reducing change outputs or adding inputs when necessary.\n"
989  "It may add a new change output if one does not already exist.\n"
990  "All inputs in the original transaction will be included in the replacement transaction.\n"
991  "The command will fail if the wallet or mempool contains a transaction that spends one of T's outputs.\n"
992  "By default, the new fee will be calculated automatically using the estimatesmartfee RPC.\n"
993  "The user can specify a confirmation target for estimatesmartfee.\n"
994  "Alternatively, the user can specify a fee rate in " + CURRENCY_ATOM + "/vB for the new transaction.\n"
995  "At a minimum, the new fee rate must be high enough to pay an additional new relay fee (incrementalfee\n"
996  "returned by getnetworkinfo) to enter the node's mempool.\n"
997  "* WARNING: before version 0.21, fee_rate was in " + CURRENCY_UNIT + "/kvB. As of 0.21, fee_rate is in " + CURRENCY_ATOM + "/vB. *\n",
998  {
999  {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The txid to be bumped"},
1001  {
1002  {"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks\n"},
1003  {"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"},
1004  "\nSpecify a fee rate in " + CURRENCY_ATOM + "/vB instead of relying on the built-in fee estimator.\n"
1005  "Must be at least " + incremental_fee + " higher than the current transaction fee rate.\n"
1006  "WARNING: before version 0.21, fee_rate was in " + CURRENCY_UNIT + "/kvB. As of 0.21, fee_rate is in " + CURRENCY_ATOM + "/vB.\n"},
1007  {"replaceable", RPCArg::Type::BOOL, RPCArg::Default{true}, "Whether the new transaction should still be\n"
1008  "marked bip-125 replaceable. If true, the sequence numbers in the transaction will\n"
1009  "be left unchanged from the original. If false, any input sequence numbers in the\n"
1010  "original transaction that were less than 0xfffffffe will be increased to 0xfffffffe\n"
1011  "so the new transaction will not be explicitly bip-125 replaceable (though it may\n"
1012  "still be replaceable in practice, for example if it has unconfirmed ancestors which\n"
1013  "are replaceable).\n"},
1014  {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n"
1015  "\"" + FeeModes("\"\n\"") + "\""},
1016  {"outputs", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "The outputs specified as key-value pairs.\n"
1017  "Each key may only appear once, i.e. there can only be one 'data' output, and no address may be duplicated.\n"
1018  "At least one output of either type must be specified.\n"
1019  "Cannot be provided if 'original_change_index' is specified.",
1020  OutputsDoc(),
1021  RPCArgOptions{.skip_type_check = true}},
1022  {"original_change_index", RPCArg::Type::NUM, RPCArg::DefaultHint{"not set, detect change automatically"}, "The 0-based index of the change output on the original transaction. "
1023  "The indicated output will be recycled into the new change output on the bumped transaction. "
1024  "The remainder after paying the recipients and fees will be sent to the output script of the "
1025  "original change output. The change output’s amount can increase if bumping the transaction "
1026  "adds new inputs, otherwise it will decrease. Cannot be used in combination with the 'outputs' option."},
1027  },
1028  RPCArgOptions{.oneline_description="options"}},
1029  },
1030  RPCResult{
1031  RPCResult::Type::OBJ, "", "", Cat(
1032  want_psbt ?
1033  std::vector<RPCResult>{{RPCResult::Type::STR, "psbt", "The base64-encoded unsigned PSBT of the new transaction."}} :
1034  std::vector<RPCResult>{{RPCResult::Type::STR_HEX, "txid", "The id of the new transaction."}},
1035  {
1036  {RPCResult::Type::STR_AMOUNT, "origfee", "The fee of the replaced transaction."},
1037  {RPCResult::Type::STR_AMOUNT, "fee", "The fee of the new transaction."},
1038  {RPCResult::Type::ARR, "errors", "Errors encountered during processing (may be empty).",
1039  {
1040  {RPCResult::Type::STR, "", ""},
1041  }},
1042  })
1043  },
1044  RPCExamples{
1045  "\nBump the fee, get the new transaction\'s " + std::string(want_psbt ? "psbt" : "txid") + "\n" +
1046  HelpExampleCli(method_name, "<txid>")
1047  },
1048  [want_psbt](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
1049 {
1050  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
1051  if (!pwallet) return UniValue::VNULL;
1052 
1053  if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !pwallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER) && !want_psbt) {
1054  throw JSONRPCError(RPC_WALLET_ERROR, "bumpfee is not available with wallets that have private keys disabled. Use psbtbumpfee instead.");
1055  }
1056 
1057  uint256 hash(ParseHashV(request.params[0], "txid"));
1058 
1059  CCoinControl coin_control;
1060  coin_control.fAllowWatchOnly = pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
1061  // optional parameters
1062  coin_control.m_signal_bip125_rbf = true;
1063  std::vector<CTxOut> outputs;
1064 
1065  std::optional<uint32_t> original_change_index;
1066 
1067  if (!request.params[1].isNull()) {
1068  UniValue options = request.params[1];
1069  RPCTypeCheckObj(options,
1070  {
1071  {"confTarget", UniValueType(UniValue::VNUM)},
1072  {"conf_target", UniValueType(UniValue::VNUM)},
1073  {"fee_rate", UniValueType()}, // will be checked by AmountFromValue() in SetFeeEstimateMode()
1074  {"replaceable", UniValueType(UniValue::VBOOL)},
1075  {"estimate_mode", UniValueType(UniValue::VSTR)},
1076  {"outputs", UniValueType()}, // will be checked by AddOutputs()
1077  {"original_change_index", UniValueType(UniValue::VNUM)},
1078  },
1079  true, true);
1080 
1081  if (options.exists("confTarget") && options.exists("conf_target")) {
1082  throw JSONRPCError(RPC_INVALID_PARAMETER, "confTarget and conf_target options should not both be set. Use conf_target (confTarget is deprecated).");
1083  }
1084 
1085  auto conf_target = options.exists("confTarget") ? options["confTarget"] : options["conf_target"];
1086 
1087  if (options.exists("replaceable")) {
1088  coin_control.m_signal_bip125_rbf = options["replaceable"].get_bool();
1089  }
1090  SetFeeEstimateMode(*pwallet, coin_control, conf_target, options["estimate_mode"], options["fee_rate"], /*override_min_fee=*/false);
1091 
1092  // Prepare new outputs by creating a temporary tx and calling AddOutputs().
1093  if (!options["outputs"].isNull()) {
1094  if (options["outputs"].isArray() && options["outputs"].empty()) {
1095  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, output argument cannot be an empty array");
1096  }
1097  CMutableTransaction tempTx;
1098  AddOutputs(tempTx, options["outputs"]);
1099  outputs = tempTx.vout;
1100  }
1101 
1102  if (options.exists("original_change_index")) {
1103  original_change_index = options["original_change_index"].getInt<uint32_t>();
1104  }
1105  }
1106 
1107  // Make sure the results are valid at least up to the most recent block
1108  // the user could have gotten from another RPC command prior to now
1109  pwallet->BlockUntilSyncedToCurrentChain();
1110 
1111  LOCK(pwallet->cs_wallet);
1112 
1113  EnsureWalletIsUnlocked(*pwallet);
1114 
1115 
1116  std::vector<bilingual_str> errors;
1117  CAmount old_fee;
1118  CAmount new_fee;
1119  CMutableTransaction mtx;
1120  feebumper::Result res;
1121  // Targeting feerate bump.
1122  res = feebumper::CreateRateBumpTransaction(*pwallet, hash, coin_control, errors, old_fee, new_fee, mtx, /*require_mine=*/ !want_psbt, outputs, original_change_index);
1123  if (res != feebumper::Result::OK) {
1124  switch(res) {
1126  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, errors[0].original);
1127  break;
1129  throw JSONRPCError(RPC_INVALID_REQUEST, errors[0].original);
1130  break;
1132  throw JSONRPCError(RPC_INVALID_PARAMETER, errors[0].original);
1133  break;
1135  throw JSONRPCError(RPC_WALLET_ERROR, errors[0].original);
1136  break;
1137  default:
1138  throw JSONRPCError(RPC_MISC_ERROR, errors[0].original);
1139  break;
1140  }
1141  }
1142 
1143  UniValue result(UniValue::VOBJ);
1144 
1145  // For bumpfee, return the new transaction id.
1146  // For psbtbumpfee, return the base64-encoded unsigned PSBT of the new transaction.
1147  if (!want_psbt) {
1148  if (!feebumper::SignTransaction(*pwallet, mtx)) {
1149  if (pwallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER)) {
1150  throw JSONRPCError(RPC_WALLET_ERROR, "Transaction incomplete. Try psbtbumpfee instead.");
1151  }
1152  throw JSONRPCError(RPC_WALLET_ERROR, "Can't sign transaction.");
1153  }
1154 
1155  uint256 txid;
1156  if (feebumper::CommitTransaction(*pwallet, hash, std::move(mtx), errors, txid) != feebumper::Result::OK) {
1157  throw JSONRPCError(RPC_WALLET_ERROR, errors[0].original);
1158  }
1159 
1160  result.pushKV("txid", txid.GetHex());
1161  } else {
1162  PartiallySignedTransaction psbtx(mtx);
1163  bool complete = false;
1164  const TransactionError err = pwallet->FillPSBT(psbtx, complete, SIGHASH_DEFAULT, /*sign=*/false, /*bip32derivs=*/true);
1166  CHECK_NONFATAL(!complete);
1167  DataStream ssTx{};
1168  ssTx << psbtx;
1169  result.pushKV("psbt", EncodeBase64(ssTx.str()));
1170  }
1171 
1172  result.pushKV("origfee", ValueFromAmount(old_fee));
1173  result.pushKV("fee", ValueFromAmount(new_fee));
1174  UniValue result_errors(UniValue::VARR);
1175  for (const bilingual_str& error : errors) {
1176  result_errors.push_back(error.original);
1177  }
1178  result.pushKV("errors", result_errors);
1179 
1180  return result;
1181 },
1182  };
1183 }
1184 
1185 RPCHelpMan bumpfee() { return bumpfee_helper("bumpfee"); }
1186 RPCHelpMan psbtbumpfee() { return bumpfee_helper("psbtbumpfee"); }
1187 
1189 {
1190  return RPCHelpMan{"send",
1191  "\nEXPERIMENTAL warning: this call may be changed in future releases.\n"
1192  "\nSend a transaction.\n",
1193  {
1194  {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The outputs specified as key-value pairs.\n"
1195  "Each key may only appear once, i.e. there can only be one 'data' output, and no address may be duplicated.\n"
1196  "At least one output of either type must be specified.\n"
1197  "For convenience, a dictionary, which holds the key-value pairs directly, is also accepted.",
1198  OutputsDoc(),
1199  RPCArgOptions{.skip_type_check = true}},
1200  {"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"},
1201  {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n"
1202  "\"" + FeeModes("\"\n\"") + "\""},
1203  {"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
1205  Cat<std::vector<RPCArg>>(
1206  {
1207  {"add_inputs", RPCArg::Type::BOOL, RPCArg::DefaultHint{"false when \"inputs\" are specified, true otherwise"},"Automatically include coins from the wallet to cover the target amount.\n"},
1208  {"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include inputs that are not safe to spend (unconfirmed transactions from outside keys and unconfirmed replacement transactions).\n"
1209  "Warning: the resulting transaction may become invalid if one of the unsafe inputs disappears.\n"
1210  "If that happens, you will need to fund the transaction with different inputs and republish it."},
1211  {"minconf", RPCArg::Type::NUM, RPCArg::Default{0}, "If add_inputs is specified, require inputs with at least this many confirmations."},
1212  {"maxconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "If add_inputs is specified, require inputs with at most this many confirmations."},
1213  {"add_to_wallet", RPCArg::Type::BOOL, RPCArg::Default{true}, "When false, returns a serialized transaction which will not be added to the wallet or broadcast"},
1214  {"change_address", RPCArg::Type::STR, RPCArg::DefaultHint{"automatic"}, "The bitcoin address to receive the change"},
1215  {"change_position", RPCArg::Type::NUM, RPCArg::DefaultHint{"random"}, "The index of the change output"},
1216  {"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if change_address is not specified. Options are \"legacy\", \"p2sh-segwit\", \"bech32\" and \"bech32m\"."},
1217  {"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB.", RPCArgOptions{.also_positional = true}},
1218  {"include_watching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch only.\n"
1219  "Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
1220  "e.g. with 'importpubkey' or 'importmulti' with the 'pubkeys' or 'desc' field."},
1221  {"inputs", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "Specify inputs instead of adding them automatically. A JSON array of JSON objects",
1222  {
1223  {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
1224  {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
1225  {"sequence", RPCArg::Type::NUM, RPCArg::Optional::NO, "The sequence number"},
1226  {"weight", RPCArg::Type::NUM, RPCArg::DefaultHint{"Calculated from wallet and solving data"}, "The maximum weight for this input, "
1227  "including the weight of the outpoint and sequence number. "
1228  "Note that signature sizes are not guaranteed to be consistent, "
1229  "so the maximum DER signatures size of 73 bytes should be used when considering ECDSA signatures."
1230  "Remember to convert serialized sizes to weight units when necessary."},
1231  },
1232  },
1233  {"locktime", RPCArg::Type::NUM, RPCArg::Default{0}, "Raw locktime. Non-0 value also locktime-activates inputs"},
1234  {"lock_unspents", RPCArg::Type::BOOL, RPCArg::Default{false}, "Lock selected unspent outputs"},
1235  {"psbt", RPCArg::Type::BOOL, RPCArg::DefaultHint{"automatic"}, "Always return a PSBT, implies add_to_wallet=false."},
1236  {"subtract_fee_from_outputs", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "Outputs to subtract the fee from, specified as integer indices.\n"
1237  "The fee will be equally deducted from the amount of each specified output.\n"
1238  "Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
1239  "If no outputs are specified here, the sender pays the fee.",
1240  {
1241  {"vout_index", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "The zero-based output index, before a change output is added."},
1242  },
1243  },
1244  },
1245  FundTxDoc()),
1246  RPCArgOptions{.oneline_description="options"}},
1247  },
1248  RPCResult{
1249  RPCResult::Type::OBJ, "", "",
1250  {
1251  {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
1252  {RPCResult::Type::STR_HEX, "txid", /*optional=*/true, "The transaction id for the send. Only 1 transaction is created regardless of the number of addresses."},
1253  {RPCResult::Type::STR_HEX, "hex", /*optional=*/true, "If add_to_wallet is false, the hex-encoded raw transaction with signature(s)"},
1254  {RPCResult::Type::STR, "psbt", /*optional=*/true, "If more signatures are needed, or if add_to_wallet is false, the base64-encoded (partially) signed transaction"}
1255  }
1256  },
1257  RPCExamples{""
1258  "\nSend 0.1 BTC with a confirmation target of 6 blocks in economical fee estimate mode\n"
1259  + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.1}' 6 economical\n") +
1260  "Send 0.2 BTC with a fee rate of 1.1 " + CURRENCY_ATOM + "/vB using positional arguments\n"
1261  + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.2}' null \"unset\" 1.1\n") +
1262  "Send 0.2 BTC with a fee rate of 1 " + CURRENCY_ATOM + "/vB using the options argument\n"
1263  + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.2}' null \"unset\" null '{\"fee_rate\": 1}'\n") +
1264  "Send 0.3 BTC with a fee rate of 25 " + CURRENCY_ATOM + "/vB using named arguments\n"
1265  + HelpExampleCli("-named send", "outputs='{\"" + EXAMPLE_ADDRESS[0] + "\": 0.3}' fee_rate=25\n") +
1266  "Create a transaction that should confirm the next block, with a specific input, and return result without adding to wallet or broadcasting to the network\n"
1267  + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.1}' 1 economical '{\"add_to_wallet\": false, \"inputs\": [{\"txid\":\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\", \"vout\":1}]}'")
1268  },
1269  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
1270  {
1271  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
1272  if (!pwallet) return UniValue::VNULL;
1273 
1274  UniValue options{request.params[4].isNull() ? UniValue::VOBJ : request.params[4]};
1275  InterpretFeeEstimationInstructions(/*conf_target=*/request.params[1], /*estimate_mode=*/request.params[2], /*fee_rate=*/request.params[3], options);
1276  PreventOutdatedOptions(options);
1277 
1278 
1279  bool rbf{options.exists("replaceable") ? options["replaceable"].get_bool() : pwallet->m_signal_rbf};
1280  UniValue outputs(UniValue::VOBJ);
1281  outputs = NormalizeOutputs(request.params[0]);
1282  std::vector<CRecipient> recipients = CreateRecipients(
1283  ParseOutputs(outputs),
1284  InterpretSubtractFeeFromOutputInstructions(options["subtract_fee_from_outputs"], outputs.getKeys())
1285  );
1286  CMutableTransaction rawTx = ConstructTransaction(options["inputs"], request.params[0], options["locktime"], rbf);
1287  CCoinControl coin_control;
1288  // Automatically select coins, unless at least one is manually selected. Can
1289  // be overridden by options.add_inputs.
1290  coin_control.m_allow_other_inputs = rawTx.vin.size() == 0;
1291  SetOptionsInputWeights(options["inputs"], options);
1292  // Clear tx.vout since it is not meant to be used now that we are passing outputs directly.
1293  // This sets us up for a future PR to completely remove tx from the function signature in favor of passing inputs directly
1294  rawTx.vout.clear();
1295  auto txr = FundTransaction(*pwallet, rawTx, recipients, options, coin_control, /*override_min_fee=*/false);
1296 
1297  return FinishTransaction(pwallet, options, CMutableTransaction(*txr.tx));
1298  }
1299  };
1300 }
1301 
1303 {
1304  return RPCHelpMan{"sendall",
1305  "EXPERIMENTAL warning: this call may be changed in future releases.\n"
1306  "\nSpend the value of all (or specific) confirmed UTXOs in the wallet to one or more recipients.\n"
1307  "Unconfirmed inbound UTXOs and locked UTXOs will not be spent. Sendall will respect the avoid_reuse wallet flag.\n"
1308  "If your wallet contains many small inputs, either because it received tiny payments or as a result of accumulating change, consider using `send_max` to exclude inputs that are worth less than the fees needed to spend them.\n",
1309  {
1310  {"recipients", RPCArg::Type::ARR, RPCArg::Optional::NO, "The sendall destinations. Each address may only appear once.\n"
1311  "Optionally some recipients can be specified with an amount to perform payments, but at least one address must appear without a specified amount.\n",
1312  {
1313  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "A bitcoin address which receives an equal share of the unspecified amount."},
1315  {
1316  {"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "A key-value pair. The key (string) is the bitcoin address, the value (float or string) is the amount in " + CURRENCY_UNIT + ""},
1317  },
1318  },
1319  },
1320  },
1321  {"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"},
1322  {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n"
1323  "\"" + FeeModes("\"\n\"") + "\""},
1324  {"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
1325  {
1327  Cat<std::vector<RPCArg>>(
1328  {
1329  {"add_to_wallet", RPCArg::Type::BOOL, RPCArg::Default{true}, "When false, returns the serialized transaction without broadcasting or adding it to the wallet"},
1330  {"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB.", RPCArgOptions{.also_positional = true}},
1331  {"include_watching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch-only.\n"
1332  "Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
1333  "e.g. with 'importpubkey' or 'importmulti' with the 'pubkeys' or 'desc' field."},
1334  {"inputs", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "Use exactly the specified inputs to build the transaction. Specifying inputs is incompatible with the send_max, minconf, and maxconf options.",
1335  {
1337  {
1338  {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
1339  {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
1340  {"sequence", RPCArg::Type::NUM, RPCArg::DefaultHint{"depends on the value of the 'replaceable' and 'locktime' arguments"}, "The sequence number"},
1341  },
1342  },
1343  },
1344  },
1345  {"locktime", RPCArg::Type::NUM, RPCArg::Default{0}, "Raw locktime. Non-0 value also locktime-activates inputs"},
1346  {"lock_unspents", RPCArg::Type::BOOL, RPCArg::Default{false}, "Lock selected unspent outputs"},
1347  {"psbt", RPCArg::Type::BOOL, RPCArg::DefaultHint{"automatic"}, "Always return a PSBT, implies add_to_wallet=false."},
1348  {"send_max", RPCArg::Type::BOOL, RPCArg::Default{false}, "When true, only use UTXOs that can pay for their own fees to maximize the output amount. When 'false' (default), no UTXO is left behind. send_max is incompatible with providing specific inputs."},
1349  {"minconf", RPCArg::Type::NUM, RPCArg::Default{0}, "Require inputs with at least this many confirmations."},
1350  {"maxconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "Require inputs with at most this many confirmations."},
1351  },
1352  FundTxDoc()
1353  ),
1355  },
1356  },
1357  RPCResult{
1358  RPCResult::Type::OBJ, "", "",
1359  {
1360  {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
1361  {RPCResult::Type::STR_HEX, "txid", /*optional=*/true, "The transaction id for the send. Only 1 transaction is created regardless of the number of addresses."},
1362  {RPCResult::Type::STR_HEX, "hex", /*optional=*/true, "If add_to_wallet is false, the hex-encoded raw transaction with signature(s)"},
1363  {RPCResult::Type::STR, "psbt", /*optional=*/true, "If more signatures are needed, or if add_to_wallet is false, the base64-encoded (partially) signed transaction"}
1364  }
1365  },
1366  RPCExamples{""
1367  "\nSpend all UTXOs from the wallet with a fee rate of 1 " + CURRENCY_ATOM + "/vB using named arguments\n"
1368  + HelpExampleCli("-named sendall", "recipients='[\"" + EXAMPLE_ADDRESS[0] + "\"]' fee_rate=1\n") +
1369  "Spend all UTXOs with a fee rate of 1.1 " + CURRENCY_ATOM + "/vB using positional arguments\n"
1370  + HelpExampleCli("sendall", "'[\"" + EXAMPLE_ADDRESS[0] + "\"]' null \"unset\" 1.1\n") +
1371  "Spend all UTXOs split into equal amounts to two addresses with a fee rate of 1.5 " + CURRENCY_ATOM + "/vB using the options argument\n"
1372  + HelpExampleCli("sendall", "'[\"" + EXAMPLE_ADDRESS[0] + "\", \"" + EXAMPLE_ADDRESS[1] + "\"]' null \"unset\" null '{\"fee_rate\": 1.5}'\n") +
1373  "Leave dust UTXOs in wallet, spend only UTXOs with positive effective value with a fee rate of 10 " + CURRENCY_ATOM + "/vB using the options argument\n"
1374  + HelpExampleCli("sendall", "'[\"" + EXAMPLE_ADDRESS[0] + "\"]' null \"unset\" null '{\"fee_rate\": 10, \"send_max\": true}'\n") +
1375  "Spend all UTXOs with a fee rate of 1.3 " + CURRENCY_ATOM + "/vB using named arguments and sending a 0.25 " + CURRENCY_UNIT + " to another recipient\n"
1376  + HelpExampleCli("-named sendall", "recipients='[{\"" + EXAMPLE_ADDRESS[1] + "\": 0.25}, \""+ EXAMPLE_ADDRESS[0] + "\"]' fee_rate=1.3\n")
1377  },
1378  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
1379  {
1380  std::shared_ptr<CWallet> const pwallet{GetWalletForJSONRPCRequest(request)};
1381  if (!pwallet) return UniValue::VNULL;
1382  // Make sure the results are valid at least up to the most recent block
1383  // the user could have gotten from another RPC command prior to now
1384  pwallet->BlockUntilSyncedToCurrentChain();
1385 
1386  UniValue options{request.params[4].isNull() ? UniValue::VOBJ : request.params[4]};
1387  InterpretFeeEstimationInstructions(/*conf_target=*/request.params[1], /*estimate_mode=*/request.params[2], /*fee_rate=*/request.params[3], options);
1388  PreventOutdatedOptions(options);
1389 
1390 
1391  std::set<std::string> addresses_without_amount;
1392  UniValue recipient_key_value_pairs(UniValue::VARR);
1393  const UniValue& recipients{request.params[0]};
1394  for (unsigned int i = 0; i < recipients.size(); ++i) {
1395  const UniValue& recipient{recipients[i]};
1396  if (recipient.isStr()) {
1397  UniValue rkvp(UniValue::VOBJ);
1398  rkvp.pushKV(recipient.get_str(), 0);
1399  recipient_key_value_pairs.push_back(rkvp);
1400  addresses_without_amount.insert(recipient.get_str());
1401  } else {
1402  recipient_key_value_pairs.push_back(recipient);
1403  }
1404  }
1405 
1406  if (addresses_without_amount.size() == 0) {
1407  throw JSONRPCError(RPC_INVALID_PARAMETER, "Must provide at least one address without a specified amount");
1408  }
1409 
1410  CCoinControl coin_control;
1411 
1412  SetFeeEstimateMode(*pwallet, coin_control, options["conf_target"], options["estimate_mode"], options["fee_rate"], /*override_min_fee=*/false);
1413 
1414  coin_control.fAllowWatchOnly = ParseIncludeWatchonly(options["include_watching"], *pwallet);
1415 
1416  if (options.exists("minconf")) {
1417  if (options["minconf"].getInt<int>() < 0)
1418  {
1419  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid minconf (minconf cannot be negative): %s", options["minconf"].getInt<int>()));
1420  }
1421 
1422  coin_control.m_min_depth = options["minconf"].getInt<int>();
1423  }
1424 
1425  if (options.exists("maxconf")) {
1426  coin_control.m_max_depth = options["maxconf"].getInt<int>();
1427 
1428  if (coin_control.m_max_depth < coin_control.m_min_depth) {
1429  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("maxconf can't be lower than minconf: %d < %d", coin_control.m_max_depth, coin_control.m_min_depth));
1430  }
1431  }
1432 
1433  const bool rbf{options.exists("replaceable") ? options["replaceable"].get_bool() : pwallet->m_signal_rbf};
1434 
1435  FeeCalculation fee_calc_out;
1436  CFeeRate fee_rate{GetMinimumFeeRate(*pwallet, coin_control, &fee_calc_out)};
1437  // Do not, ever, assume that it's fine to change the fee rate if the user has explicitly
1438  // provided one
1439  if (coin_control.m_feerate && fee_rate > *coin_control.m_feerate) {
1440  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee rate (%s) is lower than the minimum fee rate setting (%s)", coin_control.m_feerate->ToString(FeeEstimateMode::SAT_VB), fee_rate.ToString(FeeEstimateMode::SAT_VB)));
1441  }
1442  if (fee_calc_out.reason == FeeReason::FALLBACK && !pwallet->m_allow_fallback_fee) {
1443  // eventually allow a fallback fee
1444  throw JSONRPCError(RPC_WALLET_ERROR, "Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.");
1445  }
1446 
1447  CMutableTransaction rawTx{ConstructTransaction(options["inputs"], recipient_key_value_pairs, options["locktime"], rbf)};
1448  LOCK(pwallet->cs_wallet);
1449 
1450  CAmount total_input_value(0);
1451  bool send_max{options.exists("send_max") ? options["send_max"].get_bool() : false};
1452  if (options.exists("inputs") && options.exists("send_max")) {
1453  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot combine send_max with specific inputs.");
1454  } else if (options.exists("inputs") && (options.exists("minconf") || options.exists("maxconf"))) {
1455  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot combine minconf or maxconf with specific inputs.");
1456  } else if (options.exists("inputs")) {
1457  for (const CTxIn& input : rawTx.vin) {
1458  if (pwallet->IsSpent(input.prevout)) {
1459  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input not available. UTXO (%s:%d) was already spent.", input.prevout.hash.ToString(), input.prevout.n));
1460  }
1461  const CWalletTx* tx{pwallet->GetWalletTx(input.prevout.hash)};
1462  if (!tx || input.prevout.n >= tx->tx->vout.size() || !(pwallet->IsMine(tx->tx->vout[input.prevout.n]) & (coin_control.fAllowWatchOnly ? ISMINE_ALL : ISMINE_SPENDABLE))) {
1463  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input not found. UTXO (%s:%d) is not part of wallet.", input.prevout.hash.ToString(), input.prevout.n));
1464  }
1465  total_input_value += tx->tx->vout[input.prevout.n].nValue;
1466  }
1467  } else {
1468  CoinFilterParams coins_params;
1469  coins_params.min_amount = 0;
1470  for (const COutput& output : AvailableCoins(*pwallet, &coin_control, fee_rate, coins_params).All()) {
1471  CHECK_NONFATAL(output.input_bytes > 0);
1472  if (send_max && fee_rate.GetFee(output.input_bytes) > output.txout.nValue) {
1473  continue;
1474  }
1475  CTxIn input(output.outpoint.hash, output.outpoint.n, CScript(), rbf ? MAX_BIP125_RBF_SEQUENCE : CTxIn::SEQUENCE_FINAL);
1476  rawTx.vin.push_back(input);
1477  total_input_value += output.txout.nValue;
1478  }
1479  }
1480 
1481  // estimate final size of tx
1482  const TxSize tx_size{CalculateMaximumSignedTxSize(CTransaction(rawTx), pwallet.get())};
1483  const CAmount fee_from_size{fee_rate.GetFee(tx_size.vsize)};
1484  const CAmount effective_value{total_input_value - fee_from_size};
1485 
1486  if (fee_from_size > pwallet->m_default_max_tx_fee) {
1488  }
1489 
1490  if (effective_value <= 0) {
1491  if (send_max) {
1492  throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Total value of UTXO pool too low to pay for transaction, try using lower feerate.");
1493  } else {
1494  throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Total value of UTXO pool too low to pay for transaction. Try using lower feerate or excluding uneconomic UTXOs with 'send_max' option.");
1495  }
1496  }
1497 
1498  // If this transaction is too large, e.g. because the wallet has many UTXOs, it will be rejected by the node's mempool.
1499  if (tx_size.weight > MAX_STANDARD_TX_WEIGHT) {
1500  throw JSONRPCError(RPC_WALLET_ERROR, "Transaction too large.");
1501  }
1502 
1503  CAmount output_amounts_claimed{0};
1504  for (const CTxOut& out : rawTx.vout) {
1505  output_amounts_claimed += out.nValue;
1506  }
1507 
1508  if (output_amounts_claimed > total_input_value) {
1509  throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Assigned more value to outputs than available funds.");
1510  }
1511 
1512  const CAmount remainder{effective_value - output_amounts_claimed};
1513  if (remainder < 0) {
1514  throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds for fees after creating specified outputs.");
1515  }
1516 
1517  const CAmount per_output_without_amount{remainder / (long)addresses_without_amount.size()};
1518 
1519  bool gave_remaining_to_first{false};
1520  for (CTxOut& out : rawTx.vout) {
1521  CTxDestination dest;
1522  ExtractDestination(out.scriptPubKey, dest);
1523  std::string addr{EncodeDestination(dest)};
1524  if (addresses_without_amount.count(addr) > 0) {
1525  out.nValue = per_output_without_amount;
1526  if (!gave_remaining_to_first) {
1527  out.nValue += remainder % addresses_without_amount.size();
1528  gave_remaining_to_first = true;
1529  }
1530  if (IsDust(out, pwallet->chain().relayDustFee())) {
1531  // Dynamically generated output amount is dust
1532  throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Dynamically assigned remainder results in dust output.");
1533  }
1534  } else {
1535  if (IsDust(out, pwallet->chain().relayDustFee())) {
1536  // Specified output amount is dust
1537  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Specified output amount to %s is below dust threshold.", addr));
1538  }
1539  }
1540  }
1541 
1542  const bool lock_unspents{options.exists("lock_unspents") ? options["lock_unspents"].get_bool() : false};
1543  if (lock_unspents) {
1544  for (const CTxIn& txin : rawTx.vin) {
1545  pwallet->LockCoin(txin.prevout);
1546  }
1547  }
1548 
1549  return FinishTransaction(pwallet, options, rawTx);
1550  }
1551  };
1552 }
1553 
1555 {
1556  return RPCHelpMan{"walletprocesspsbt",
1557  "\nUpdate a PSBT with input information from our wallet and then sign inputs\n"
1558  "that we can sign for." +
1560  {
1561  {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction base64 string"},
1562  {"sign", RPCArg::Type::BOOL, RPCArg::Default{true}, "Also sign the transaction when updating (requires wallet to be unlocked)"},
1563  {"sighashtype", RPCArg::Type::STR, RPCArg::Default{"DEFAULT for Taproot, ALL otherwise"}, "The signature hash type to sign with if not specified by the PSBT. Must be one of\n"
1564  " \"DEFAULT\"\n"
1565  " \"ALL\"\n"
1566  " \"NONE\"\n"
1567  " \"SINGLE\"\n"
1568  " \"ALL|ANYONECANPAY\"\n"
1569  " \"NONE|ANYONECANPAY\"\n"
1570  " \"SINGLE|ANYONECANPAY\""},
1571  {"bip32derivs", RPCArg::Type::BOOL, RPCArg::Default{true}, "Include BIP 32 derivation paths for public keys if we know them"},
1572  {"finalize", RPCArg::Type::BOOL, RPCArg::Default{true}, "Also finalize inputs if possible"},
1573  },
1574  RPCResult{
1575  RPCResult::Type::OBJ, "", "",
1576  {
1577  {RPCResult::Type::STR, "psbt", "The base64-encoded partially signed transaction"},
1578  {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
1579  {RPCResult::Type::STR_HEX, "hex", /*optional=*/true, "The hex-encoded network transaction if complete"},
1580  }
1581  },
1582  RPCExamples{
1583  HelpExampleCli("walletprocesspsbt", "\"psbt\"")
1584  },
1585  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
1586 {
1587  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
1588  if (!pwallet) return UniValue::VNULL;
1589 
1590  const CWallet& wallet{*pwallet};
1591  // Make sure the results are valid at least up to the most recent block
1592  // the user could have gotten from another RPC command prior to now
1593  wallet.BlockUntilSyncedToCurrentChain();
1594 
1595  // Unserialize the transaction
1597  std::string error;
1598  if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
1599  throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
1600  }
1601 
1602  // Get the sighash type
1603  int nHashType = ParseSighashString(request.params[2]);
1604 
1605  // Fill transaction with our data and also sign
1606  bool sign = request.params[1].isNull() ? true : request.params[1].get_bool();
1607  bool bip32derivs = request.params[3].isNull() ? true : request.params[3].get_bool();
1608  bool finalize = request.params[4].isNull() ? true : request.params[4].get_bool();
1609  bool complete = true;
1610 
1611  if (sign) EnsureWalletIsUnlocked(*pwallet);
1612 
1613  const TransactionError err{wallet.FillPSBT(psbtx, complete, nHashType, sign, bip32derivs, nullptr, finalize)};
1614  if (err != TransactionError::OK) {
1615  throw JSONRPCTransactionError(err);
1616  }
1617 
1618  UniValue result(UniValue::VOBJ);
1619  DataStream ssTx{};
1620  ssTx << psbtx;
1621  result.pushKV("psbt", EncodeBase64(ssTx.str()));
1622  result.pushKV("complete", complete);
1623  if (complete) {
1624  CMutableTransaction mtx;
1625  // Returns true if complete, which we already think it is.
1627  DataStream ssTx_final;
1628  ssTx_final << TX_WITH_WITNESS(mtx);
1629  result.pushKV("hex", HexStr(ssTx_final));
1630  }
1631 
1632  return result;
1633 },
1634  };
1635 }
1636 
1638 {
1639  return RPCHelpMan{"walletcreatefundedpsbt",
1640  "\nCreates and funds a transaction in the Partially Signed Transaction format.\n"
1641  "Implements the Creator and Updater roles.\n"
1642  "All existing inputs must either have their previous output transaction be in the wallet\n"
1643  "or be in the UTXO set. Solving data must be provided for non-wallet inputs.\n",
1644  {
1645  {"inputs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "Leave empty to add inputs automatically. See add_inputs option.",
1646  {
1648  {
1649  {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
1650  {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
1651  {"sequence", RPCArg::Type::NUM, RPCArg::DefaultHint{"depends on the value of the 'locktime' and 'options.replaceable' arguments"}, "The sequence number"},
1652  {"weight", RPCArg::Type::NUM, RPCArg::DefaultHint{"Calculated from wallet and solving data"}, "The maximum weight for this input, "
1653  "including the weight of the outpoint and sequence number. "
1654  "Note that signature sizes are not guaranteed to be consistent, "
1655  "so the maximum DER signatures size of 73 bytes should be used when considering ECDSA signatures."
1656  "Remember to convert serialized sizes to weight units when necessary."},
1657  },
1658  },
1659  },
1660  },
1661  {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The outputs specified as key-value pairs.\n"
1662  "Each key may only appear once, i.e. there can only be one 'data' output, and no address may be duplicated.\n"
1663  "At least one output of either type must be specified.\n"
1664  "For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n"
1665  "accepted as second parameter.",
1666  OutputsDoc(),
1667  RPCArgOptions{.skip_type_check = true}},
1668  {"locktime", RPCArg::Type::NUM, RPCArg::Default{0}, "Raw locktime. Non-0 value also locktime-activates inputs"},
1670  Cat<std::vector<RPCArg>>(
1671  {
1672  {"add_inputs", RPCArg::Type::BOOL, RPCArg::DefaultHint{"false when \"inputs\" are specified, true otherwise"}, "Automatically include coins from the wallet to cover the target amount.\n"},
1673  {"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include inputs that are not safe to spend (unconfirmed transactions from outside keys and unconfirmed replacement transactions).\n"
1674  "Warning: the resulting transaction may become invalid if one of the unsafe inputs disappears.\n"
1675  "If that happens, you will need to fund the transaction with different inputs and republish it."},
1676  {"minconf", RPCArg::Type::NUM, RPCArg::Default{0}, "If add_inputs is specified, require inputs with at least this many confirmations."},
1677  {"maxconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "If add_inputs is specified, require inputs with at most this many confirmations."},
1678  {"changeAddress", RPCArg::Type::STR, RPCArg::DefaultHint{"automatic"}, "The bitcoin address to receive the change"},
1679  {"changePosition", RPCArg::Type::NUM, RPCArg::DefaultHint{"random"}, "The index of the change output"},
1680  {"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
1681  {"includeWatching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch only"},
1682  {"lockUnspents", RPCArg::Type::BOOL, RPCArg::Default{false}, "Lock selected unspent outputs"},
1683  {"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
1684  {"feeRate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_UNIT + "/kvB."},
1685  {"subtractFeeFromOutputs", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "The outputs to subtract the fee from.\n"
1686  "The fee will be equally deducted from the amount of each specified output.\n"
1687  "Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
1688  "If no outputs are specified here, the sender pays the fee.",
1689  {
1690  {"vout_index", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "The zero-based output index, before a change output is added."},
1691  },
1692  },
1693  },
1694  FundTxDoc()),
1695  RPCArgOptions{.oneline_description="options"}},
1696  {"bip32derivs", RPCArg::Type::BOOL, RPCArg::Default{true}, "Include BIP 32 derivation paths for public keys if we know them"},
1697  },
1698  RPCResult{
1699  RPCResult::Type::OBJ, "", "",
1700  {
1701  {RPCResult::Type::STR, "psbt", "The resulting raw transaction (base64-encoded string)"},
1702  {RPCResult::Type::STR_AMOUNT, "fee", "Fee in " + CURRENCY_UNIT + " the resulting transaction pays"},
1703  {RPCResult::Type::NUM, "changepos", "The position of the added change output, or -1"},
1704  }
1705  },
1706  RPCExamples{
1707  "\nCreate a transaction with no inputs\n"
1708  + HelpExampleCli("walletcreatefundedpsbt", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"")
1709  },
1710  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
1711 {
1712  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
1713  if (!pwallet) return UniValue::VNULL;
1714 
1715  CWallet& wallet{*pwallet};
1716  // Make sure the results are valid at least up to the most recent block
1717  // the user could have gotten from another RPC command prior to now
1718  wallet.BlockUntilSyncedToCurrentChain();
1719 
1720  UniValue options{request.params[3].isNull() ? UniValue::VOBJ : request.params[3]};
1721 
1722  const UniValue &replaceable_arg = options["replaceable"];
1723  const bool rbf{replaceable_arg.isNull() ? wallet.m_signal_rbf : replaceable_arg.get_bool()};
1724  CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], rbf);
1725  UniValue outputs(UniValue::VOBJ);
1726  outputs = NormalizeOutputs(request.params[1]);
1727  std::vector<CRecipient> recipients = CreateRecipients(
1728  ParseOutputs(outputs),
1729  InterpretSubtractFeeFromOutputInstructions(options["subtractFeeFromOutputs"], outputs.getKeys())
1730  );
1731  CCoinControl coin_control;
1732  // Automatically select coins, unless at least one is manually selected. Can
1733  // be overridden by options.add_inputs.
1734  coin_control.m_allow_other_inputs = rawTx.vin.size() == 0;
1735  SetOptionsInputWeights(request.params[0], options);
1736  // Clear tx.vout since it is not meant to be used now that we are passing outputs directly.
1737  // This sets us up for a future PR to completely remove tx from the function signature in favor of passing inputs directly
1738  rawTx.vout.clear();
1739  auto txr = FundTransaction(wallet, rawTx, recipients, options, coin_control, /*override_min_fee=*/true);
1740 
1741  // Make a blank psbt
1743 
1744  // Fill transaction with out data but don't sign
1745  bool bip32derivs = request.params[4].isNull() ? true : request.params[4].get_bool();
1746  bool complete = true;
1747  const TransactionError err{wallet.FillPSBT(psbtx, complete, 1, /*sign=*/false, /*bip32derivs=*/bip32derivs)};
1748  if (err != TransactionError::OK) {
1749  throw JSONRPCTransactionError(err);
1750  }
1751 
1752  // Serialize the PSBT
1753  DataStream ssTx{};
1754  ssTx << psbtx;
1755 
1756  UniValue result(UniValue::VOBJ);
1757  result.pushKV("psbt", EncodeBase64(ssTx.str()));
1758  result.pushKV("fee", ValueFromAmount(txr.fee));
1759  result.pushKV("changepos", txr.change_pos ? (int)*txr.change_pos : -1);
1760  return result;
1761 },
1762  };
1763 }
1764 } // namespace wallet
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
Definition: addresstype.cpp:49
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
Definition: addresstype.h:131
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
static CAmount AmountFromValue(const UniValue &value)
Definition: bitcoin-tx.cpp:555
ArgsManager & args
Definition: bitcoind.cpp:268
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:73
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
Definition: feerate.h:33
std::string ToString(const FeeEstimateMode &fee_estimate_mode=FeeEstimateMode::BTC_KVB) const
Definition: feerate.cpp:39
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:29
uint32_t n
Definition: transaction.h:32
Txid hash
Definition: transaction.h:31
An encapsulated public key.
Definition: pubkey.h:34
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:164
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid())
Definition: pubkey.cpp:304
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:414
A reference to a CScript: the Hash160 of its serialization.
Definition: script.h:583
The basic transaction that is broadcasted on the network and contained in blocks.
Definition: transaction.h:296
An input of a transaction.
Definition: transaction.h:67
static const uint32_t SEQUENCE_FINAL
Setting nSequence to this value for every input in a transaction disables nLockTime/IsFinalTx().
Definition: transaction.h:81
COutPoint prevout
Definition: transaction.h:69
An output of a transaction.
Definition: transaction.h:150
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:147
Fast randomness source.
Definition: random.h:145
void push_back(UniValue val)
Definition: univalue.cpp:104
const std::string & get_str() const
const UniValue & find_value(std::string_view key) const
Definition: univalue.cpp:233
@ VNULL
Definition: univalue.h:24
@ VOBJ
Definition: univalue.h:24
@ VSTR
Definition: univalue.h:24
@ VARR
Definition: univalue.h:24
@ VNUM
Definition: univalue.h:24
@ VBOOL
Definition: univalue.h:24
bool isNull() const
Definition: univalue.h:79
const UniValue & get_obj() const
size_t size() const
Definition: univalue.h:71
enum VType type() const
Definition: univalue.h:126
const std::vector< UniValue > & getValues() const
const std::vector< std::string > & getKeys() const
bool isBool() const
Definition: univalue.h:82
Int getInt() const
Definition: univalue.h:138
bool exists(const std::string &key) const
Definition: univalue.h:77
bool isNum() const
Definition: univalue.h:84
void pushKV(std::string key, UniValue val)
Definition: univalue.cpp:126
bool get_bool() const
std::string GetHex() const
Definition: uint256.cpp:11
std::string ToString() const
static transaction_identifier FromUint256(const uint256 &id)
256-bit opaque blob.
Definition: uint256.h:106
Coin Control Features.
Definition: coincontrol.h:81
FeeEstimateMode m_fee_mode
Fee estimation mode to control arguments to estimateSmartFee.
Definition: coincontrol.h:107
std::optional< bool > m_signal_bip125_rbf
Override the wallet's m_signal_rbf if set.
Definition: coincontrol.h:101
std::optional< unsigned int > m_confirm_target
Override the default confirmation target if set.
Definition: coincontrol.h:99
std::optional< OutputType > m_change_type
Override the default change type if set, ignored if destChange is set.
Definition: coincontrol.h:86
bool m_avoid_address_reuse
Forbids inclusion of dirty (previously used) addresses.
Definition: coincontrol.h:105
int m_min_depth
Minimum chain depth value for coin availability.
Definition: coincontrol.h:109
bool m_allow_other_inputs
If true, the selection process can add extra unselected inputs from the wallet while requires all sel...
Definition: coincontrol.h:91
int m_max_depth
Maximum chain depth value for coin availability.
Definition: coincontrol.h:111
bool fOverrideFeeRate
Override automatic min/max checks on fee, m_feerate must be set if true.
Definition: coincontrol.h:95
void SetInputWeight(const COutPoint &outpoint, int64_t weight)
Set an input's weight.
Definition: coincontrol.cpp:67
std::optional< CFeeRate > m_feerate
Override the wallet's m_pay_tx_fee if set.
Definition: coincontrol.h:97
bool m_include_unsafe_inputs
If false, only safe inputs will be used.
Definition: coincontrol.h:88
bool m_avoid_partial_spends
Avoid partial use of funds sent to a given address.
Definition: coincontrol.h:103
bool fAllowWatchOnly
Includes watch only addresses which are solvable.
Definition: coincontrol.h:93
FlatSigningProvider m_external_provider
SigningProvider that has pubkeys and scripts to do spend size estimation for external inputs.
Definition: coincontrol.h:113
CTxDestination destChange
Custom change destination, if not set an address is generated.
Definition: coincontrol.h:84
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:301
A transaction with a bunch of additional info that only the owner cares about.
Definition: transaction.h:177
static UniValue Parse(std::string_view raw)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
Definition: client.cpp:318
static int64_t GetTransactionInputWeight(const CTxIn &txin)
Definition: validation.h:157
std::string EncodeHexTx(const CTransaction &tx)
Definition: core_write.cpp:143
UniValue ValueFromAmount(const CAmount amount)
Definition: core_write.cpp:26
bool DecodeHexTx(CMutableTransaction &tx, const std::string &hex_tx, bool try_no_witness=false, bool try_witness=true)
Definition: core_read.cpp:194
bilingual_str TransactionErrorString(const TransactionError err)
Definition: error.cpp:13
TransactionError
Definition: error.h:22
const std::string CURRENCY_ATOM
Definition: feerate.h:18
const std::string CURRENCY_UNIT
Definition: feerate.h:17
@ SAT_VB
Use sat/vB fee rate unit.
@ SIGHASH_DEFAULT
Taproot only; implied when sighash byte is missing, and equivalent to SIGHASH_ALL.
Definition: interpreter.h:35
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
Definition: key_io.cpp:292
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:287
bilingual_str ErrorString(const Result< T > &result)
Definition: result.h:81
Result CreateRateBumpTransaction(CWallet &wallet, const uint256 &txid, const CCoinControl &coin_control, std::vector< bilingual_str > &errors, CAmount &old_fee, CAmount &new_fee, CMutableTransaction &mtx, bool require_mine, const std::vector< CTxOut > &outputs, std::optional< uint32_t > original_change_index)
Create bumpfee transaction based on feerate estimates.
Definition: feebumper.cpp:164
Result CommitTransaction(CWallet &wallet, const uint256 &txid, CMutableTransaction &&mtx, std::vector< bilingual_str > &errors, uint256 &bumped_txid)
Commit the bumpfee transaction.
Definition: feebumper.cpp:355
bool SignTransaction(CWallet &wallet, CMutableTransaction &mtx)
Sign the new transaction,.
Definition: feebumper.cpp:335
std::vector< CRecipient > CreateRecipients(const std::vector< std::pair< CTxDestination, CAmount >> &outputs, const std::set< int > &subtract_fee_outputs)
Definition: spend.cpp:27
CreatedTransactionResult FundTransaction(CWallet &wallet, const CMutableTransaction &tx, const std::vector< CRecipient > &recipients, const UniValue &options, CCoinControl &coinControl, bool override_min_fee)
Definition: spend.cpp:493
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: util.cpp:72
util::Result< CreatedTransactionResult > CreateTransaction(CWallet &wallet, const std::vector< CRecipient > &vecSend, std::optional< unsigned int > change_pos, const CCoinControl &coin_control, bool sign)
Create a new transaction paying the recipients with a set of coins selected by SelectCoins(); Also cr...
Definition: spend.cpp:1335
std::set< int > InterpretSubtractFeeFromOutputInstructions(const UniValue &sffo_instructions, const std::vector< std::string > &destinations)
Definition: spend.cpp:60
std::map< std::string, std::string > mapValue_t
Definition: transaction.h:149
static RPCHelpMan bumpfee_helper(std::string method_name)
Definition: spend.cpp:979
RPCHelpMan walletprocesspsbt()
Definition: spend.cpp:1554
void EnsureWalletIsUnlocked(const CWallet &wallet)
Definition: util.cpp:96
const std::string HELP_REQUIRING_PASSPHRASE
Definition: util.cpp:20
RPCHelpMan psbtbumpfee()
Definition: spend.cpp:1186
static void SetFeeEstimateMode(const CWallet &wallet, CCoinControl &cc, const UniValue &conf_target, const UniValue &estimate_mode, const UniValue &fee_rate, bool override_min_fee)
Update coin control with fee estimation based on the given parameters.
Definition: spend.cpp:199
RPCHelpMan walletcreatefundedpsbt()
Definition: spend.cpp:1637
static void InterpretFeeEstimationInstructions(const UniValue &conf_target, const UniValue &estimate_mode, const UniValue &fee_rate, UniValue &options)
Definition: spend.cpp:38
static void SetOptionsInputWeights(const UniValue &inputs, UniValue &options)
Definition: spend.cpp:715
RPCHelpMan settxfee()
Definition: spend.cpp:411
RPCHelpMan signrawtransactionwithwallet()
Definition: spend.cpp:864
CFeeRate GetMinimumFeeRate(const CWallet &wallet, const CCoinControl &coin_control, FeeCalculation *feeCalc)
Estimate the minimum fee rate considering user set parameters and the required fee.
Definition: fees.cpp:29
UniValue SendMoney(CWallet &wallet, const CCoinControl &coin_control, std::vector< CRecipient > &recipients, mapValue_t map_value, bool verbose)
Definition: spend.cpp:156
RPCHelpMan sendall()
Definition: spend.cpp:1302
static void PreventOutdatedOptions(const UniValue &options)
Definition: spend.cpp:134
RPCHelpMan bumpfee()
Definition: spend.cpp:1185
@ ISMINE_SPENDABLE
Definition: types.h:43
@ ISMINE_ALL
Definition: types.h:45
static UniValue FinishTransaction(const std::shared_ptr< CWallet > pwallet, const UniValue &options, const CMutableTransaction &rawTx)
Definition: spend.cpp:91
bool ParseIncludeWatchonly(const UniValue &include_watchonly, const CWallet &wallet)
Used by RPC commands that have an include_watchonly parameter.
Definition: util.cpp:51
RPCHelpMan sendmany()
Definition: spend.cpp:317
bool GetAvoidReuseFlag(const CWallet &wallet, const UniValue &param)
Definition: util.cpp:36
static std::vector< RPCArg > OutputsDoc()
Definition: spend.cpp:961
RPCHelpMan fundrawtransaction()
Definition: spend.cpp:732
TxSize CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector< CTxOut > &txouts, const CCoinControl *coin_control)
Calculate the size of the transaction using CoinControl to determine whether to expect signature grin...
Definition: spend.cpp:133
static std::vector< RPCArg > FundTxDoc(bool solving_data=true)
Definition: spend.cpp:454
@ WALLET_FLAG_EXTERNAL_SIGNER
Indicates that the wallet needs an external signer.
Definition: walletutil.h:77
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
Definition: walletutil.h:51
RPCHelpMan send()
Definition: spend.cpp:1188
RPCHelpMan sendtoaddress()
Definition: spend.cpp:223
CoinsResult AvailableCoins(const CWallet &wallet, const CCoinControl *coinControl, std::optional< CFeeRate > feerate, const CoinFilterParams &params)
Populate the CoinsResult struct with vectors of available COutputs, organized by OutputType.
Definition: spend.cpp:305
std::optional< OutputType > ParseOutputType(const std::string &type)
Definition: outputtype.cpp:24
bool IsDust(const CTxOut &txout, const CFeeRate &dustRelayFeeIn)
Definition: policy.cpp:65
static constexpr unsigned int DEFAULT_INCREMENTAL_RELAY_FEE
Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or rep...
Definition: policy.h:35
static constexpr int32_t MAX_STANDARD_TX_WEIGHT
The maximum weight for transactions we're willing to relay/mine.
Definition: policy.h:27
static constexpr TransactionSerParams TX_WITH_WITNESS
Definition: transaction.h:195
static CTransactionRef MakeTransactionRef(Tx &&txIn)
Definition: transaction.h:424
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:423
bool DecodeBase64PSBT(PartiallySignedTransaction &psbt, const std::string &base64_tx, std::string &error)
Decode a base64ed PSBT into a PartiallySignedTransaction.
Definition: psbt.cpp:536
bool FinalizeAndExtractPSBT(PartiallySignedTransaction &psbtx, CMutableTransaction &result)
Finalizes a PSBT if possible, and extracts it to a CMutableTransaction if it could be finalized.
Definition: psbt.cpp:495
void SignTransactionResultToJSON(CMutableTransaction &mtx, bool complete, const std::map< COutPoint, Coin > &coins, const std::map< int, bilingual_str > &input_errors, UniValue &result)
CMutableTransaction ConstructTransaction(const UniValue &inputs_in, const UniValue &outputs_in, const UniValue &locktime, std::optional< bool > rbf)
Create a transaction from univalue parameters.
void AddOutputs(CMutableTransaction &rawTx, const UniValue &outputs_in)
Normalize, parse, and add outputs to the transaction.
void ParsePrevouts(const UniValue &prevTxsUnival, FillableSigningProvider *keystore, std::map< COutPoint, Coin > &coins)
Parse a prevtxs UniValue array and get the map of coins from it.
UniValue NormalizeOutputs(const UniValue &outputs_in)
Normalize univalue-represented outputs.
std::vector< std::pair< CTxDestination, CAmount > > ParseOutputs(const UniValue &outputs)
Parse normalized outputs into destination, amount tuples.
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:58
@ RPC_MISC_ERROR
General application defined errors.
Definition: protocol.h:39
@ RPC_WALLET_INSUFFICIENT_FUNDS
Not enough funds in wallet or account.
Definition: protocol.h:72
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition: protocol.h:43
@ RPC_WALLET_ERROR
Wallet errors.
Definition: protocol.h:71
@ RPC_DESERIALIZATION_ERROR
Error parsing or validating structure in raw format.
Definition: protocol.h:45
@ RPC_INVALID_REQUEST
Standard JSON-RPC 2.0 errors.
Definition: protocol.h:28
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
Definition: protocol.h:41
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:155
int ParseSighashString(const UniValue &sighash)
Returns a sighash value corresponding to the passed in argument.
Definition: util.cpp:339
UniValue JSONRPCTransactionError(TransactionError terr, const std::string &err_string)
Definition: util.cpp:380
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:173
const std::string EXAMPLE_ADDRESS[2]
Example bech32 addresses for the RPCExamples help documentation.
Definition: util.cpp:31
uint256 ParseHashO(const UniValue &o, std::string_view strKey)
Definition: util.cpp:98
unsigned int ParseConfirmTarget(const UniValue &value, unsigned int max_target)
Parse a confirm target option and raise an RPC error if it is invalid.
Definition: util.cpp:351
void RPCTypeCheckObj(const UniValue &o, const std::map< std::string, UniValueType > &typesExpected, bool fAllowNull, bool fStrict)
Definition: util.cpp:43
uint256 ParseHashV(const UniValue &v, std::string_view name)
Utilities: convert hex-encoded Values (throws error if not hex).
Definition: util.cpp:89
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
Definition: strencodings.h:65
A mutable version of CTransaction.
Definition: transaction.h:378
std::vector< CTxOut > vout
Definition: transaction.h:380
std::vector< CTxIn > vin
Definition: transaction.h:379
FeeReason reason
Definition: fees.h:95
FlatSigningProvider & Merge(FlatSigningProvider &&b) LIFETIMEBOUND
std::map< CKeyID, CPubKey > pubkeys
std::map< CScriptID, CScript > scripts
A version of CTransaction with the PSBT format.
Definition: psbt.h:947
@ OBJ_USER_KEYS
Special type where the user must set the keys e.g. to define multiple addresses; as opposed to e....
@ STR_HEX
Special type that is a STR with only hex chars.
@ AMOUNT
Special type representing a floating point amount (can be either NUM or STR)
@ OBJ_NAMED_PARAMS
Special type that behaves almost exactly like OBJ, defining an options object with a list of pre-defi...
std::string DefaultHint
Hint for default value.
Definition: util.h:200
@ OMITTED
Optional argument for which the default value is omitted from help text for one of two reasons:
@ NO
Required arg.
std::string oneline_description
Should be empty unless it is supposed to override the auto-generated summary line.
Definition: util.h:151
bool also_positional
If set allows a named-parameter field in an OBJ_NAMED_PARAM options object to have the same name as a...
Definition: util.h:154
bool skip_type_check
Definition: util.h:150
@ STR_HEX
Special string with only hex chars.
@ STR_AMOUNT
Special string to represent a floating point amount.
Wrapper for UniValue::VType, which includes typeAny: Used to denote don't care type.
Definition: util.h:74
Bilingual messages:
Definition: translation.h:18
A UTXO under consideration for use in funding a new transaction.
Definition: coinselection.h:28
#define LOCK(cs)
Definition: sync.h:257
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1162
const UniValue NullUniValue
Definition: univalue.cpp:16
std::string FeeModes(const std::string &delimiter)
Definition: fees.cpp:47
std::string InvalidEstimateModeErrorMessage()
Definition: fees.cpp:52
bool FeeModeFromString(const std::string &mode_string, FeeEstimateMode &fee_estimate_mode)
Definition: fees.cpp:57
std::string StringForFeeReason(FeeReason reason)
Definition: fees.cpp:17
static constexpr uint32_t MAX_BIP125_RBF_SEQUENCE
Definition: rbf.h:12
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::string EncodeBase64(Span< const unsigned char > input)
bool IsHex(std::string_view str)
V Cat(V v1, V &&v2)
Concatenate two vectors, moving elements.
Definition: vector.h:34