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