Coverage Report

Created: 2026-07-08 14:14

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