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