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