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