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