bitcoin core ipc fuzz coverage

Coverage Report

Created: 2026-08-26 16:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/home/enochazariah/dev/bitcoin-invariants/src/rpc/rawtransaction.cpp
Line
Count
Source
1
// Copyright (c) 2010 Satoshi Nakamoto
2
// Copyright (c) 2009-present The Bitcoin Core developers
3
// Distributed under the MIT software license, see the accompanying
4
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6
#include <base58.h>
7
#include <chain.h>
8
#include <coins.h>
9
#include <consensus/amount.h>
10
#include <consensus/validation.h>
11
#include <core_io.h>
12
#include <index/txindex.h>
13
#include <key_io.h>
14
#include <node/blockstorage.h>
15
#include <node/coin.h>
16
#include <node/context.h>
17
#include <node/psbt.h>
18
#include <node/transaction.h>
19
#include <node/types.h>
20
#include <policy/packages.h>
21
#include <policy/policy.h>
22
#include <policy/rbf.h>
23
#include <primitives/transaction.h>
24
#include <psbt.h>
25
#include <random.h>
26
#include <rpc/blockchain.h>
27
#include <rpc/rawtransaction_util.h>
28
#include <rpc/server.h>
29
#include <rpc/server_util.h>
30
#include <rpc/util.h>
31
#include <script/script.h>
32
#include <script/sign.h>
33
#include <script/signingprovider.h>
34
#include <script/solver.h>
35
#include <uint256.h>
36
#include <undo.h>
37
#include <util/bip32.h>
38
#include <util/check.h>
39
#include <util/strencodings.h>
40
#include <util/string.h>
41
#include <util/vector.h>
42
#include <validation.h>
43
#include <validationinterface.h>
44
45
#include <cstdint>
46
#include <numeric>
47
48
#include <univalue.h>
49
50
using node::AnalyzePSBT;
51
using node::FindCoins;
52
using node::GetTransaction;
53
using node::NodeContext;
54
using node::PSBTAnalysis;
55
56
static constexpr decltype(CTransaction::version) DEFAULT_RAWTX_VERSION{CTransaction::CURRENT_VERSION};
57
58
static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry,
59
                     Chainstate& active_chainstate, const CTxUndo* txundo = nullptr,
60
                     TxVerbosity verbosity = TxVerbosity::SHOW_DETAILS)
61
0
{
62
0
    CHECK_NONFATAL(verbosity >= TxVerbosity::SHOW_DETAILS);
Line
Count
Source
113
0
    inline_check_non_fatal(condition, std::source_location::current(), #condition)
63
    // Call into TxToUniv() in bitcoin-common to decode the transaction hex.
64
    //
65
    // Blockchain contextual information (confirmations and blocktime) is not
66
    // available to code in bitcoin-common, so we query them here and push the
67
    // data into the returned UniValue.
68
0
    TxToUniv(tx, /*block_hash=*/uint256(), entry, /*include_hex=*/true, txundo, verbosity);
69
70
0
    if (!hashBlock.IsNull()) {
71
0
        LOCK(cs_main);
Line
Count
Source
268
0
#define LOCK(cs) UniqueLock BITCOIN_UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
Line
Count
Source
11
0
#define BITCOIN_UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
Line
Count
Source
9
0
#define PASTE2(x, y) PASTE(x, y)
Line
Count
Source
8
0
#define PASTE(x, y) x ## y
72
73
0
        entry.pushKV("blockhash", hashBlock.GetHex());
74
0
        const CBlockIndex* pindex = active_chainstate.m_blockman.LookupBlockIndex(hashBlock);
75
0
        if (pindex) {
76
0
            if (active_chainstate.m_chain.Contains(*pindex)) {
77
0
                entry.pushKV("confirmations", 1 + active_chainstate.m_chain.Height() - pindex->nHeight);
78
0
                entry.pushKV("time", pindex->GetBlockTime());
79
0
                entry.pushKV("blocktime", pindex->GetBlockTime());
80
0
            }
81
0
            else
82
0
                entry.pushKV("confirmations", 0);
83
0
        }
84
0
    }
85
0
}
86
87
static std::vector<RPCArg> CreateTxDoc()
88
0
{
89
0
    return {
90
0
        {"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The inputs",
91
0
            {
92
0
                {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
93
0
                    {
94
0
                        {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
95
0
                        {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
96
0
                        {"sequence", RPCArg::Type::NUM, RPCArg::DefaultHint{"depends on the value of the 'replaceable' and 'locktime' arguments"}, "The sequence number"},
97
0
                    },
98
0
                },
99
0
            },
100
0
        },
101
0
        {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The outputs specified as key-value pairs.\n"
102
0
                "Each key may only appear once, i.e. there can only be one 'data' output, and no address may be duplicated.\n"
103
0
                "At least one output of either type must be specified.\n"
104
0
                "For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n"
105
0
                "                             accepted as second parameter.",
106
0
            {
107
0
                {"", RPCArg::Type::OBJ_USER_KEYS, RPCArg::Optional::OMITTED, "",
108
0
                    {
109
0
                        {"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},
110
0
                    },
111
0
                },
112
0
                {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
113
0
                    {
114
0
                        {"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"},
115
0
                    },
116
0
                },
117
0
            },
118
0
         RPCArgOptions{.skip_type_check = true}},
119
0
        {"locktime", RPCArg::Type::NUM, RPCArg::Default{0}, "Raw locktime. Non-0 value also locktime-activates inputs"},
120
0
        {"replaceable", RPCArg::Type::BOOL, RPCArg::Default{true}, "Marks this transaction as BIP125-replaceable.\n"
121
0
                "Allows this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible."},
122
0
        {"version", RPCArg::Type::NUM, RPCArg::Default{DEFAULT_RAWTX_VERSION}, "Transaction version"},
123
0
    };
124
0
}
125
126
// Update PSBT with information from the mempool, the UTXO set, the txindex, and the provided descriptors.
127
// Optionally, sign the inputs that we can using information from the descriptors.
128
PartiallySignedTransaction ProcessPSBT(const std::string& psbt_string, const std::any& context, const HidingSigningProvider& provider, std::optional<int> sighash_type, bool finalize)
129
0
{
130
    // Unserialize the transactions
131
0
    util::Result<PartiallySignedTransaction> psbt_res = DecodeBase64PSBT(psbt_string);
132
0
    if (!psbt_res) {
133
0
        throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", util::ErrorString(psbt_res).original));
Line
Count
Source
1172
0
#define strprintf tfm::format
134
0
    }
135
0
    PartiallySignedTransaction psbtx = *psbt_res;
136
137
0
    if (g_txindex) g_txindex->BlockUntilSyncedToCurrentChain();
138
0
    const NodeContext& node = EnsureAnyNodeContext(context);
139
140
    // If we can't find the corresponding full transaction for all of our inputs,
141
    // this will be used to find just the utxos for the segwit inputs for which
142
    // the full transaction isn't found
143
0
    std::map<COutPoint, Coin> coins;
144
145
    // Fetch previous transactions:
146
    // First, look in the txindex and the mempool
147
0
    for (PSBTInput& psbt_input : psbtx.inputs) {
148
        // The `non_witness_utxo` is the whole previous transaction
149
0
        if (psbt_input.non_witness_utxo) continue;
150
151
0
        CTransactionRef tx;
152
153
        // Look in the txindex
154
0
        if (g_txindex) {
155
0
            uint256 block_hash;
156
0
            g_txindex->FindTx(psbt_input.prev_txid, block_hash, tx);
157
0
        }
158
        // If we still don't have it look in the mempool
159
0
        if (!tx) {
160
0
            tx = node.mempool->get(psbt_input.prev_txid);
161
0
        }
162
0
        if (tx) {
163
0
            psbt_input.non_witness_utxo = tx;
164
0
        } else {
165
0
            coins[psbt_input.GetOutPoint()]; // Create empty map entry keyed by prevout
166
0
        }
167
0
    }
168
169
    // If we still haven't found all of the inputs, look for the missing ones in the utxo set
170
0
    if (!coins.empty()) {
171
0
        FindCoins(node, coins);
172
0
        for (PSBTInput& input : psbtx.inputs) {
173
            // If there are still missing utxos, add them if they were found in the utxo set
174
0
            if (!input.non_witness_utxo) {
175
0
                const Coin& coin = coins.at(input.GetOutPoint());
176
0
                if (!coin.out.IsNull() && IsSegWitOutput(provider, coin.out.scriptPubKey)) {
177
0
                    input.witness_utxo = coin.out;
178
0
                }
179
0
            }
180
0
        }
181
0
    }
182
183
0
    std::optional<PrecomputedTransactionData> txdata_res = PrecomputePSBTData(psbtx);
184
0
    if (!txdata_res) {
185
0
        throw JSONRPCPSBTError(common::PSBTError::INVALID_TX);
186
0
    }
187
0
    const PrecomputedTransactionData& txdata = *txdata_res;
188
189
0
    for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {
190
0
        if (PSBTInputSigned(psbtx.inputs.at(i))) {
191
0
            continue;
192
0
        }
193
194
        // Update script/keypath information using descriptor data.
195
        // Note that SignPSBTInput does a lot more than just constructing ECDSA signatures.
196
        // We only actually care about those if our signing provider doesn't hide private
197
        // information, as is the case with `descriptorprocesspsbt`
198
        // Only error for mismatching sighash types as it is critical that the sighash to sign with matches the PSBT's
199
0
        if (SignPSBTInput(provider, psbtx, /*index=*/i, &txdata, {.sighash_type = sighash_type, .finalize = finalize}, /*out_sigdata=*/nullptr) == common::PSBTError::SIGHASH_MISMATCH) {
200
0
            throw JSONRPCPSBTError(common::PSBTError::SIGHASH_MISMATCH);
201
0
        }
202
0
    }
203
204
    // Update script/keypath information using descriptor data.
205
0
    for (unsigned int i = 0; i < psbtx.outputs.size(); ++i) {
206
0
        UpdatePSBTOutput(provider, psbtx, i);
207
0
    }
208
209
0
    RemoveUnnecessaryTransactions(psbtx);
210
211
0
    return psbtx;
212
0
}
213
214
static RPCMethod getrawtransaction()
215
0
{
216
0
    const std::vector<RPCResult> verbosity_1_block{
217
0
        {RPCResult::Type::BOOL, "in_active_chain", /*optional=*/true, "Whether specified block is in the active chain or not (only present with explicit \"blockhash\" argument)"},
218
0
        {RPCResult::Type::STR_HEX, "blockhash", /*optional=*/true, "the block hash"},
219
0
        {RPCResult::Type::NUM, "vsize_adjusted", /*optional=*/true, "Sigop-adjusted virtual size in bytes, present for mempool transactions."},
220
0
        {RPCResult::Type::NUM, "confirmations", /*optional=*/true, "The confirmations"},
221
0
        {RPCResult::Type::NUM_TIME, "blocktime", /*optional=*/true, "The block time expressed in " + UNIX_EPOCH_TIME},
222
0
        {RPCResult::Type::NUM, "time", /*optional=*/true, "Same as \"blocktime\""},
223
0
        {RPCResult::Type::STR_HEX, "hex", "The serialized, hex-encoded data for 'txid'"},
224
0
    };
225
0
    const auto v2_extras = Cat<std::vector<RPCResult>>(
226
0
        std::vector<RPCResult>{{
227
0
            RPCResult::Type::NUM, "fee", /*optional=*/true,
228
0
            "transaction fee in " + CURRENCY_UNIT + ", omitted if block undo data is not available"
229
0
        }},
230
0
        TxDoc({.elision_mode = ElisionMode::Silent,
231
0
               .prevout = true,
232
0
               .prevout_optional = true,
233
0
               .vin_inner_elision = "Same vin fields as verbosity = 1"}));
234
0
    return RPCMethod{
235
0
                "getrawtransaction",
236
237
0
                "By default, this call only returns a transaction if it is in the mempool. If -txindex is enabled\n"
238
0
                "and no blockhash argument is passed, it will return the transaction if it is in the mempool or any block.\n"
239
0
                "If a blockhash argument is passed, it will return the transaction if\n"
240
0
                "the specified block is available and the transaction is in that block.\n\n"
241
0
                "Hint: Use gettransaction for wallet transactions.\n\n"
242
243
0
                "If verbosity is 0 or omitted, returns the serialized transaction as a hex-encoded string.\n"
244
0
                "If verbosity is 1, returns a JSON Object with information about the transaction.\n"
245
0
                "If verbosity is 2, returns a JSON Object with information about the transaction, including fee and prevout information.",
246
0
                {
247
0
                    {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
248
0
                    {"verbosity|verbose", RPCArg::Type::NUM, RPCArg::Default{0}, "0 for hex-encoded data, 1 for a JSON object, and 2 for JSON object with fee and prevout",
249
0
                     RPCArgOptions{.skip_type_check = true}},
250
0
                    {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "The block in which to look for the transaction"},
251
0
                },
252
0
                {
253
0
                    RPCResult{"if verbosity is not set or set to 0",
254
0
                         RPCResult::Type::STR, "data", "The serialized transaction as a hex-encoded string for 'txid'"
255
0
                     },
256
0
                     RPCResult{"if verbosity is set to 1",
257
0
                         RPCResult::Type::OBJ, "", "",
258
0
                         Cat<std::vector<RPCResult>>(
259
0
                         verbosity_1_block,
260
0
                         TxDoc({.txid_field_doc="The transaction id (same as provided)"})),
261
0
                    },
262
0
                    RPCResult{"for verbosity = 2", RPCResult::Type::OBJ, "", "",
263
0
                    Cat(ElideGroup(verbosity_1_block, "Same output as verbosity = 1"), v2_extras)},
264
0
                },
265
0
                RPCExamples{
266
0
                    HelpExampleCli("getrawtransaction", "\"mytxid\"")
267
0
            + HelpExampleCli("getrawtransaction", "\"mytxid\" 1")
268
0
            + HelpExampleRpc("getrawtransaction", "\"mytxid\", 1")
269
0
            + HelpExampleCli("getrawtransaction", "\"mytxid\" 0 \"myblockhash\"")
270
0
            + HelpExampleCli("getrawtransaction", "\"mytxid\" 1 \"myblockhash\"")
271
0
            + HelpExampleCli("getrawtransaction", "\"mytxid\" 2 \"myblockhash\"")
272
0
                },
273
0
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
274
0
{
275
0
    const NodeContext& node = EnsureAnyNodeContext(request.context);
276
0
    ChainstateManager& chainman = EnsureChainman(node);
277
278
0
    auto txid{Txid::FromUint256(ParseHashV(request.params[0], "parameter 1"))};
279
0
    const CBlockIndex* blockindex = nullptr;
280
281
0
    if (txid.ToUint256() == chainman.GetParams().GenesisBlock().hashMerkleRoot) {
282
        // Special exception for the genesis block coinbase transaction
283
0
        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "The genesis block coinbase is not considered an ordinary transaction and cannot be retrieved");
284
0
    }
285
286
0
    int verbosity{ParseVerbosity(request.params[1], /*default_verbosity=*/0, /*allow_bool=*/true)};
287
288
0
    if (!request.params[2].isNull()) {
289
0
        LOCK(cs_main);
Line
Count
Source
268
0
#define LOCK(cs) UniqueLock BITCOIN_UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
Line
Count
Source
11
0
#define BITCOIN_UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
Line
Count
Source
9
0
#define PASTE2(x, y) PASTE(x, y)
Line
Count
Source
8
0
#define PASTE(x, y) x ## y
290
291
0
        uint256 blockhash = ParseHashV(request.params[2], "parameter 3");
292
0
        blockindex = chainman.m_blockman.LookupBlockIndex(blockhash);
293
0
        if (!blockindex) {
294
0
            throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block hash not found");
295
0
        }
296
0
    }
297
298
0
    bool f_txindex_ready = false;
299
0
    if (g_txindex && !blockindex) {
300
0
        f_txindex_ready = g_txindex->BlockUntilSyncedToCurrentChain();
301
0
    }
302
303
0
    uint256 hash_block;
304
0
    const CTransactionRef tx = GetTransaction(blockindex, node.mempool.get(), txid, chainman.m_blockman, hash_block);
305
0
    if (!tx) {
306
0
        std::string errmsg;
307
0
        if (blockindex) {
308
0
            const bool block_has_data = WITH_LOCK(::cs_main, return blockindex->nStatus & BLOCK_HAVE_DATA);
Line
Count
Source
299
0
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
309
0
            if (!block_has_data) {
310
0
                throw JSONRPCError(RPC_MISC_ERROR, "Block not available");
311
0
            }
312
0
            errmsg = "No such transaction found in the provided block";
313
0
        } else if (!g_txindex) {
314
0
            errmsg = "No such mempool transaction. Use -txindex or provide a block hash to enable blockchain transaction queries";
315
0
        } else if (!f_txindex_ready) {
316
0
            errmsg = "No such mempool transaction. Blockchain transactions are still in the process of being indexed";
317
0
        } else {
318
0
            errmsg = "No such mempool or blockchain transaction";
319
0
        }
320
0
        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, errmsg + ". Use gettransaction for wallet transactions.");
321
0
    }
322
323
0
    if (verbosity <= 0) {
324
0
        return EncodeHexTx(*tx);
325
0
    }
326
327
0
    UniValue result(UniValue::VOBJ);
328
0
    if (blockindex) {
329
0
        LOCK(cs_main);
Line
Count
Source
268
0
#define LOCK(cs) UniqueLock BITCOIN_UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
Line
Count
Source
11
0
#define BITCOIN_UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
Line
Count
Source
9
0
#define PASTE2(x, y) PASTE(x, y)
Line
Count
Source
8
0
#define PASTE(x, y) x ## y
330
0
        result.pushKV("in_active_chain", chainman.ActiveChain().Contains(*blockindex));
331
0
    }
332
    // If request is verbosity >= 1 but no blockhash was given, then look up the blockindex
333
0
    if (request.params[2].isNull()) {
334
0
        LOCK(cs_main);
Line
Count
Source
268
0
#define LOCK(cs) UniqueLock BITCOIN_UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
Line
Count
Source
11
0
#define BITCOIN_UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
Line
Count
Source
9
0
#define PASTE2(x, y) PASTE(x, y)
Line
Count
Source
8
0
#define PASTE(x, y) x ## y
335
0
        blockindex = chainman.m_blockman.LookupBlockIndex(hash_block); // May be nullptr for mempool transactions
336
0
    }
337
338
    // Add sigop-adjusted virtual size if the transaction exists in the mempool.
339
0
    if (blockindex == nullptr && hash_block.IsNull() && node.mempool) {
340
0
        auto info = node.mempool->info(tx->GetHash());
341
0
        if (info.tx) {
342
0
            result.pushKV("vsize_adjusted", info.vsize);
343
0
        }
344
0
    }
345
346
0
    if (verbosity == 1) {
347
0
        TxToJSON(*tx, hash_block, result, chainman.ActiveChainstate());
348
0
        return result;
349
0
    }
350
351
0
    CBlockUndo blockUndo;
352
0
    CBlock block;
353
354
0
    if (tx->IsCoinBase() || !blockindex || WITH_LOCK(::cs_main, return !(blockindex->nStatus & BLOCK_HAVE_MASK))) {
Line
Count
Source
299
0
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
355
0
        TxToJSON(*tx, hash_block, result, chainman.ActiveChainstate());
356
0
        return result;
357
0
    }
358
0
    if (!chainman.m_blockman.ReadBlockUndo(blockUndo, *blockindex)) {
359
0
        throw JSONRPCError(RPC_INTERNAL_ERROR, "Undo data expected but can't be read. This could be due to disk corruption or a conflict with a pruning event.");
360
0
    }
361
0
    if (!chainman.m_blockman.ReadBlock(block, *blockindex)) {
362
0
        throw JSONRPCError(RPC_INTERNAL_ERROR, "Block data expected but can't be read. This could be due to disk corruption or a conflict with a pruning event.");
363
0
    }
364
365
0
    CTxUndo* undoTX {nullptr};
366
0
    auto it = std::find_if(block.vtx.begin(), block.vtx.end(), [tx](CTransactionRef t){ return *t == *tx; });
367
0
    if (it != block.vtx.end()) {
368
        // -1 as blockundo does not have coinbase tx
369
0
        undoTX = &blockUndo.vtxundo.at(it - block.vtx.begin() - 1);
370
0
    }
371
0
    TxToJSON(*tx, hash_block, result, chainman.ActiveChainstate(), undoTX, TxVerbosity::SHOW_DETAILS_AND_PREVOUT);
372
0
    return result;
373
0
},
374
0
    };
375
0
}
376
377
static RPCMethod createrawtransaction()
378
0
{
379
0
    return RPCMethod{
380
0
        "createrawtransaction",
381
0
        "Create a transaction spending the given inputs and creating new outputs.\n"
382
0
                "Outputs can be addresses or data.\n"
383
0
                "Returns hex-encoded raw transaction.\n"
384
0
                "Note that the transaction's inputs are not signed, and\n"
385
0
                "it is not stored in the wallet or transmitted to the network.\n",
386
0
                CreateTxDoc(),
387
0
                RPCResult{
388
0
                    RPCResult::Type::STR_HEX, "transaction", "hex string of the transaction"
389
0
                },
390
0
                RPCExamples{
391
0
                    HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"address\\\":0.01}]\"")
392
0
            + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"")
393
0
            + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"[{\\\"address\\\":0.01}]\"")
394
0
            + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"[{\\\"data\\\":\\\"00010203\\\"}]\"")
395
0
                },
396
0
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
397
0
{
398
0
    std::optional<bool> rbf;
399
0
    if (!request.params[3].isNull()) {
400
0
        rbf = request.params[3].get_bool();
401
0
    }
402
0
    CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], rbf, self.Arg<uint32_t>("version"));
403
404
0
    return EncodeHexTx(CTransaction(rawTx));
405
0
},
406
0
    };
407
0
}
408
409
static RPCMethod decoderawtransaction()
410
0
{
411
0
    return RPCMethod{"decoderawtransaction",
412
0
                "Return a JSON object representing the serialized, hex-encoded transaction.",
413
0
                {
414
0
                    {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction hex string"},
415
0
                    {"iswitness", RPCArg::Type::BOOL, RPCArg::DefaultHint{"depends on heuristic tests"}, "Whether the transaction hex is a serialized witness transaction.\n"
416
0
                        "If iswitness is not present, heuristic tests will be used in decoding.\n"
417
0
                        "If true, only witness deserialization will be tried.\n"
418
0
                        "If false, only non-witness deserialization will be tried.\n"
419
0
                        "This boolean should reflect whether the transaction has inputs\n"
420
0
                        "(e.g. fully valid, or on-chain transactions), if known by the caller."
421
0
                    },
422
0
                },
423
0
                RPCResult{
424
0
                    RPCResult::Type::OBJ, "", "",
425
0
                    TxDoc(),
426
0
                },
427
0
                RPCExamples{
428
0
                    HelpExampleCli("decoderawtransaction", "\"hexstring\"")
429
0
            + HelpExampleRpc("decoderawtransaction", "\"hexstring\"")
430
0
                },
431
0
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
432
0
{
433
0
    CMutableTransaction mtx;
434
435
0
    bool try_witness = request.params[1].isNull() ? true : request.params[1].get_bool();
436
0
    bool try_no_witness = request.params[1].isNull() ? true : !request.params[1].get_bool();
437
438
0
    if (!DecodeHexTx(mtx, request.params[0].get_str(), try_no_witness, try_witness)) {
439
0
        throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
440
0
    }
441
442
0
    UniValue result(UniValue::VOBJ);
443
0
    TxToUniv(CTransaction(std::move(mtx)), /*block_hash=*/uint256(), /*entry=*/result, /*include_hex=*/false);
444
445
0
    return result;
446
0
},
447
0
    };
448
0
}
449
450
static RPCMethod decodescript()
451
0
{
452
0
    return RPCMethod{
453
0
        "decodescript",
454
0
        "Decode a hex-encoded script.\n",
455
0
        {
456
0
            {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded script"},
457
0
        },
458
0
        RPCResult{
459
0
            RPCResult::Type::OBJ, "", "",
460
0
            {
461
0
                {RPCResult::Type::STR, "asm", "Disassembly of the script"},
462
0
                {RPCResult::Type::STR, "desc", "Inferred descriptor for the script"},
463
0
                {RPCResult::Type::STR, "type", "The output type (e.g. " + GetAllOutputTypes() + ")"},
464
0
                {RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},
465
0
                {RPCResult::Type::STR, "p2sh", /*optional=*/true,
466
0
                 "address of P2SH script wrapping this redeem script (not returned for types that should not be wrapped)"},
467
0
                {RPCResult::Type::OBJ, "segwit", /*optional=*/true,
468
0
                 "Result of a witness output script wrapping this redeem script (not returned for types that should not be wrapped)",
469
0
                 {
470
0
                     {RPCResult::Type::STR, "asm", "Disassembly of the output script"},
471
0
                     {RPCResult::Type::STR_HEX, "hex", "The raw output script bytes, hex-encoded"},
472
0
                     {RPCResult::Type::STR, "type", "The type of the output script (e.g. witness_v0_keyhash or witness_v0_scripthash)"},
473
0
                     {RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},
474
0
                     {RPCResult::Type::STR, "desc", "Inferred descriptor for the script"},
475
0
                     {RPCResult::Type::STR, "p2sh-segwit", "address of the P2SH script wrapping this witness redeem script"},
476
0
                 }},
477
0
            },
478
0
        },
479
0
        RPCExamples{
480
0
            HelpExampleCli("decodescript", "\"hexstring\"")
481
0
          + HelpExampleRpc("decodescript", "\"hexstring\"")
482
0
        },
483
0
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
484
0
{
485
0
    UniValue r(UniValue::VOBJ);
486
0
    CScript script;
487
0
    if (request.params[0].get_str().size() > 0){
488
0
        std::vector<unsigned char> scriptData(ParseHexV(request.params[0], "argument"));
489
0
        script = CScript(scriptData.begin(), scriptData.end());
490
0
    } else {
491
        // Empty scripts are valid
492
0
    }
493
0
    ScriptToUniv(script, /*out=*/r, /*include_hex=*/false, /*include_address=*/true);
494
495
0
    std::vector<std::vector<unsigned char>> solutions_data;
496
0
    const TxoutType which_type{Solver(script, solutions_data)};
497
498
0
    const bool can_wrap{[&] {
499
0
        switch (which_type) {
500
0
        case TxoutType::MULTISIG:
501
0
        case TxoutType::NONSTANDARD:
502
0
        case TxoutType::PUBKEY:
503
0
        case TxoutType::PUBKEYHASH:
504
0
        case TxoutType::WITNESS_V0_KEYHASH:
505
0
        case TxoutType::WITNESS_V0_SCRIPTHASH:
506
            // Can be wrapped if the checks below pass
507
0
            break;
508
0
        case TxoutType::NULL_DATA:
509
0
        case TxoutType::SCRIPTHASH:
510
0
        case TxoutType::WITNESS_UNKNOWN:
511
0
        case TxoutType::WITNESS_V1_TAPROOT:
512
0
        case TxoutType::ANCHOR:
513
            // Should not be wrapped
514
0
            return false;
515
0
        } // no default case, so the compiler can warn about missing cases
516
0
        if (!script.HasValidOps() || script.IsUnspendable()) {
517
0
            return false;
518
0
        }
519
0
        for (CScript::const_iterator it{script.begin()}; it != script.end();) {
520
0
            opcodetype op;
521
0
            CHECK_NONFATAL(script.GetOp(it, op));
Line
Count
Source
113
0
    inline_check_non_fatal(condition, std::source_location::current(), #condition)
522
0
            if (op == OP_CHECKSIGADD || IsOpSuccess(op)) {
523
0
                return false;
524
0
            }
525
0
        }
526
0
        return true;
527
0
    }()};
528
529
0
    if (can_wrap) {
530
0
        r.pushKV("p2sh", EncodeDestination(ScriptHash(script)));
531
        // P2SH and witness programs cannot be wrapped in P2WSH, if this script
532
        // is a witness program, don't return addresses for a segwit programs.
533
0
        const bool can_wrap_P2WSH{[&] {
534
0
            switch (which_type) {
535
0
            case TxoutType::MULTISIG:
536
0
            case TxoutType::PUBKEY:
537
            // Uncompressed pubkeys cannot be used with segwit checksigs.
538
            // If the script contains an uncompressed pubkey, skip encoding of a segwit program.
539
0
                for (const auto& solution : solutions_data) {
540
0
                    if ((solution.size() != 1) && !CPubKey(solution).IsCompressed()) {
541
0
                        return false;
542
0
                    }
543
0
                }
544
0
                return true;
545
0
            case TxoutType::NONSTANDARD:
546
0
            case TxoutType::PUBKEYHASH:
547
                // Can be P2WSH wrapped
548
0
                return true;
549
0
            case TxoutType::NULL_DATA:
550
0
            case TxoutType::SCRIPTHASH:
551
0
            case TxoutType::WITNESS_UNKNOWN:
552
0
            case TxoutType::WITNESS_V0_KEYHASH:
553
0
            case TxoutType::WITNESS_V0_SCRIPTHASH:
554
0
            case TxoutType::WITNESS_V1_TAPROOT:
555
0
            case TxoutType::ANCHOR:
556
                // Should not be wrapped
557
0
                return false;
558
0
            } // no default case, so the compiler can warn about missing cases
559
0
            NONFATAL_UNREACHABLE();
Line
Count
Source
134
0
    throw NonFatalCheckError { "Unreachable code reached (non-fatal)", std::source_location::current() }
560
0
        }()};
561
0
        if (can_wrap_P2WSH) {
562
0
            UniValue sr(UniValue::VOBJ);
563
0
            CScript segwitScr;
564
0
            FlatSigningProvider provider;
565
0
            if (which_type == TxoutType::PUBKEY) {
566
0
                segwitScr = GetScriptForDestination(WitnessV0KeyHash(Hash160(solutions_data[0])));
567
0
            } else if (which_type == TxoutType::PUBKEYHASH) {
568
0
                segwitScr = GetScriptForDestination(WitnessV0KeyHash(uint160{solutions_data[0]}));
569
0
            } else {
570
                // Scripts that are not fit for P2WPKH are encoded as P2WSH.
571
0
                provider.scripts[CScriptID(script)] = script;
572
0
                segwitScr = GetScriptForDestination(WitnessV0ScriptHash(script));
573
0
            }
574
0
            ScriptToUniv(segwitScr, /*out=*/sr, /*include_hex=*/true, /*include_address=*/true, /*provider=*/&provider);
575
0
            sr.pushKV("p2sh-segwit", EncodeDestination(ScriptHash(segwitScr)));
576
0
            r.pushKV("segwit", std::move(sr));
577
0
        }
578
0
    }
579
580
0
    return r;
581
0
},
582
0
    };
583
0
}
584
585
static RPCMethod combinerawtransaction()
586
0
{
587
0
    return RPCMethod{
588
0
        "combinerawtransaction",
589
0
        "Combine multiple partially signed transactions into one transaction.\n"
590
0
                "The combined transaction may be another partially signed transaction or a \n"
591
0
                "fully signed transaction.",
592
0
                {
593
0
                    {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The hex strings of partially signed transactions",
594
0
                        {
595
0
                            {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A hex-encoded raw transaction"},
596
0
                        },
597
0
                        },
598
0
                },
599
0
                RPCResult{
600
0
                    RPCResult::Type::STR, "", "The hex-encoded raw transaction with signature(s)"
601
0
                },
602
0
                RPCExamples{
603
0
                    HelpExampleCli("combinerawtransaction", R"('["myhex1", "myhex2", "myhex3"]')")
604
0
                },
605
0
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
606
0
{
607
608
0
    UniValue txs = request.params[0].get_array();
609
610
    // Can't merge < 2 items
611
0
    if (txs.size() < 2) {
612
0
        throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transactions. At least two transactions required.");
613
0
    }
614
615
0
    std::vector<CMutableTransaction> txVariants(txs.size());
616
617
0
    for (unsigned int idx = 0; idx < txs.size(); idx++) {
618
0
        if (!DecodeHexTx(txVariants[idx], txs[idx].get_str())) {
619
0
            throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed for tx %d. Make sure the tx has at least one input.", idx));
Line
Count
Source
1172
0
#define strprintf tfm::format
620
0
        }
621
0
    }
622
623
0
    { // Test Tx relation for mergeability. Strip scriptSigs and scriptWitnesses to facilitate txId comparison
624
0
        std::vector<CMutableTransaction> tx_variants_copy(txVariants);
625
0
        Txid first_txid{};
626
0
        for (unsigned int k{0}; k < tx_variants_copy.size(); ++k) {
627
            // Remove all scriptSigs and scriptWitnesses from inputs
628
0
            for (CTxIn& input : tx_variants_copy[k].vin) {
629
0
                input.scriptSig.clear();
630
0
                input.scriptWitness.SetNull();
631
0
            }
632
0
            if (k == 0) {
633
0
                first_txid = tx_variants_copy[k].GetHash();
634
0
            } else if (first_txid != tx_variants_copy[k].GetHash()) {
635
0
                throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Transaction number %d not compatible with first transaction", k+1));
Line
Count
Source
1172
0
#define strprintf tfm::format
636
0
            }
637
0
        }
638
0
    }
639
640
    // mergedTx will end up with all the signatures; it
641
    // starts as a clone of the rawtx:
642
0
    CMutableTransaction mergedTx(txVariants[0]);
643
644
    // Fetch previous transactions (inputs):
645
0
    CCoinsViewCache view{&CoinsViewEmpty::Get()};
646
0
    {
647
0
        NodeContext& node = EnsureAnyNodeContext(request.context);
648
0
        const CTxMemPool& mempool = EnsureMemPool(node);
649
0
        ChainstateManager& chainman = EnsureChainman(node);
650
0
        LOCK2(cs_main, mempool.cs);
Line
Count
Source
270
0
    UniqueLock criticalblock1(MaybeCheckNotHeld(cs1), #cs1, __FILE__, __LINE__); \
271
0
    UniqueLock criticalblock2(MaybeCheckNotHeld(cs2), #cs2, __FILE__, __LINE__)
651
0
        CCoinsViewCache &viewChain = chainman.ActiveChainstate().CoinsTip();
652
0
        CCoinsViewMemPool viewMempool(&viewChain, mempool);
653
0
        view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
654
655
0
        for (const CTxIn& txin : mergedTx.vin) {
656
0
            view.AccessCoin(txin.prevout); // Load entries from viewChain into view; can fail.
657
0
        }
658
659
0
        view.SetBackend(CoinsViewEmpty::Get()); // switch back to avoid locking mempool for too long
660
0
    }
661
662
    // Use CTransaction for the constant parts of the
663
    // transaction to avoid rehashing.
664
0
    const CTransaction txConst(mergedTx);
665
    // Sign what we can:
666
0
    for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
667
0
        CTxIn& txin = mergedTx.vin[i];
668
0
        const Coin& coin = view.AccessCoin(txin.prevout);
669
0
        if (coin.IsSpent()) {
670
0
            throw JSONRPCError(RPC_VERIFY_ERROR, "Input not found or already spent");
671
0
        }
672
0
        SignatureData sigdata;
673
674
        // ... and merge in other signatures:
675
0
        for (const CMutableTransaction& txv : txVariants) {
676
0
            if (txv.vin.size() > i) {
677
0
                sigdata.MergeSignatureData(DataFromTransaction(txv, i, coin.out));
678
0
            }
679
0
        }
680
0
        ProduceSignature(DUMMY_SIGNING_PROVIDER, MutableTransactionSignatureCreator(mergedTx, i, coin.out.nValue, {.sighash_type = SIGHASH_ALL}), coin.out.scriptPubKey, sigdata);
681
682
0
        UpdateInput(txin, sigdata);
683
0
    }
684
685
0
    return EncodeHexTx(CTransaction(mergedTx));
686
0
},
687
0
    };
688
0
}
689
690
static RPCMethod signrawtransactionwithkey()
691
0
{
692
0
    return RPCMethod{
693
0
        "signrawtransactionwithkey",
694
0
        "Sign inputs for raw transaction (serialized, hex-encoded).\n"
695
0
                "The second argument is an array of base58-encoded private\n"
696
0
                "keys that will be the only keys used to sign the transaction.\n"
697
0
                "The third optional argument (may be null) is an array of previous transaction outputs that\n"
698
0
                "this transaction depends on but may not yet be in the block chain.\n",
699
0
                {
700
0
                    {"hexstring", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction hex string"},
701
0
                    {"privkeys", RPCArg::Type::ARR, RPCArg::Optional::NO, "The base58-encoded private keys for signing",
702
0
                        {
703
0
                            {"privatekey", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "private key in base58-encoding"},
704
0
                        },
705
0
                        },
706
0
                    {"prevtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "The previous dependent transaction outputs",
707
0
                        {
708
0
                            {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
709
0
                                {
710
0
                                    {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
711
0
                                    {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
712
0
                                    {"scriptPubKey", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "output script"},
713
0
                                    {"redeemScript", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "(required for P2SH) redeem script"},
714
0
                                    {"witnessScript", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "(required for P2WSH or P2SH-P2WSH) witness script"},
715
0
                                    {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::OMITTED, "(required for Segwit inputs) the amount spent"},
716
0
                                },
717
0
                                },
718
0
                        },
719
0
                        },
720
0
                    {"sighashtype", RPCArg::Type::STR, RPCArg::Default{"DEFAULT for Taproot, ALL otherwise"}, "The signature hash type. Must be one of:\n"
721
0
            "       \"DEFAULT\"\n"
722
0
            "       \"ALL\"\n"
723
0
            "       \"NONE\"\n"
724
0
            "       \"SINGLE\"\n"
725
0
            "       \"ALL|ANYONECANPAY\"\n"
726
0
            "       \"NONE|ANYONECANPAY\"\n"
727
0
            "       \"SINGLE|ANYONECANPAY\"\n"
728
0
                    },
729
0
                },
730
0
                RPCResult{
731
0
                    RPCResult::Type::OBJ, "", "",
732
0
                    {
733
0
                        {RPCResult::Type::STR_HEX, "hex", "The hex-encoded raw transaction with signature(s)"},
734
0
                        {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
735
0
                        {RPCResult::Type::ARR, "errors", /*optional=*/true, "Script verification errors (if there are any)",
736
0
                        {
737
0
                            {RPCResult::Type::OBJ, "", "",
738
0
                            {
739
0
                                {RPCResult::Type::STR_HEX, "txid", "The hash of the referenced, previous transaction"},
740
0
                                {RPCResult::Type::NUM, "vout", "The index of the output to spent and used as input"},
741
0
                                {RPCResult::Type::ARR, "witness", "",
742
0
                                {
743
0
                                    {RPCResult::Type::STR_HEX, "witness", ""},
744
0
                                }},
745
0
                                {RPCResult::Type::STR_HEX, "scriptSig", "The hex-encoded signature script"},
746
0
                                {RPCResult::Type::NUM, "sequence", "Script sequence number"},
747
0
                                {RPCResult::Type::STR, "error", "Verification or signing error related to the input"},
748
0
                            }},
749
0
                        }},
750
0
                    }
751
0
                },
752
0
                RPCExamples{
753
0
                    HelpExampleCli("signrawtransactionwithkey", "\"myhex\" \"[\\\"key1\\\",\\\"key2\\\"]\"")
754
0
            + HelpExampleRpc("signrawtransactionwithkey", "\"myhex\", \"[\\\"key1\\\",\\\"key2\\\"]\"")
755
0
                },
756
0
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
757
0
{
758
0
    CMutableTransaction mtx;
759
0
    if (!DecodeHexTx(mtx, request.params[0].get_str())) {
760
0
        throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input.");
761
0
    }
762
763
0
    FlatSigningProvider keystore;
764
0
    const UniValue& keys = request.params[1].get_array();
765
0
    for (unsigned int idx = 0; idx < keys.size(); ++idx) {
766
0
        UniValue k = keys[idx];
767
0
        CKey key = DecodeSecret(k.get_str());
768
0
        if (!key.IsValid()) {
769
0
            throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
770
0
        }
771
772
0
        CPubKey pubkey = key.GetPubKey();
773
0
        CKeyID key_id = pubkey.GetID();
774
0
        keystore.pubkeys.emplace(key_id, pubkey);
775
0
        keystore.keys.emplace(key_id, key);
776
0
    }
777
778
    // Fetch previous transactions (inputs):
779
0
    std::map<COutPoint, Coin> coins;
780
0
    for (const CTxIn& txin : mtx.vin) {
781
0
        coins[txin.prevout]; // Create empty map entry keyed by prevout.
782
0
    }
783
0
    NodeContext& node = EnsureAnyNodeContext(request.context);
784
0
    FindCoins(node, coins);
785
786
    // Parse the prevtxs array
787
0
    ParsePrevouts(request.params[2], &keystore, coins);
788
789
0
    UniValue result(UniValue::VOBJ);
790
0
    SignTransaction(mtx, &keystore, coins, request.params[3], result);
791
0
    return result;
792
0
},
793
0
    };
794
0
}
795
796
const RPCResult& DecodePSBTInputs()
797
0
{
798
0
    static const RPCResult decodepsbt_inputs{
799
0
        RPCResult::Type::ARR, "inputs", "",
800
0
        {
801
0
            {RPCResult::Type::OBJ, "", "",
802
0
            {
803
0
                {RPCResult::Type::OBJ, "non_witness_utxo", /*optional=*/true, "Decoded network transaction for non-witness UTXOs",
804
0
                    TxDoc({.elision_mode = ElisionMode::WithSummary, .elision_summary = "The layout is the same as the output of decoderawtransaction."})
805
0
                },
806
0
                {RPCResult::Type::OBJ, "witness_utxo", /*optional=*/true, "Transaction output for witness UTXOs",
807
0
                {
808
0
                    {RPCResult::Type::NUM, "amount", "The value in " + CURRENCY_UNIT},
809
0
                    {RPCResult::Type::OBJ, "scriptPubKey", "",
810
0
                    {
811
0
                        {RPCResult::Type::STR, "asm", "Disassembly of the output script"},
812
0
                        {RPCResult::Type::STR, "desc", "Inferred descriptor for the output"},
813
0
                        {RPCResult::Type::STR_HEX, "hex", "The raw output script bytes, hex-encoded"},
814
0
                        {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
815
0
                        {RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},
816
0
                    }},
817
0
                }},
818
0
                {RPCResult::Type::OBJ_DYN, "partial_signatures", /*optional=*/true, "",
819
0
                {
820
0
                    {RPCResult::Type::STR, "pubkey", "The public key and signature that corresponds to it."},
821
0
                }},
822
0
                {RPCResult::Type::STR, "sighash", /*optional=*/true, "The sighash type to be used"},
823
0
                {RPCResult::Type::OBJ, "redeem_script", /*optional=*/true, "",
824
0
                {
825
0
                    {RPCResult::Type::STR, "asm", "Disassembly of the redeem script"},
826
0
                    {RPCResult::Type::STR_HEX, "hex", "The raw redeem script bytes, hex-encoded"},
827
0
                    {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
828
0
                }},
829
0
                {RPCResult::Type::OBJ, "witness_script", /*optional=*/true, "",
830
0
                {
831
0
                    {RPCResult::Type::STR, "asm", "Disassembly of the witness script"},
832
0
                    {RPCResult::Type::STR_HEX, "hex", "The raw witness script bytes, hex-encoded"},
833
0
                    {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
834
0
                }},
835
0
                {RPCResult::Type::ARR, "bip32_derivs", /*optional=*/true, "",
836
0
                {
837
0
                    {RPCResult::Type::OBJ, "", "",
838
0
                    {
839
0
                        {RPCResult::Type::STR, "pubkey", "The public key with the derivation path as the value."},
840
0
                        {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
841
0
                        {RPCResult::Type::STR, "path", "The path"},
842
0
                    }},
843
0
                }},
844
0
                {RPCResult::Type::OBJ, "final_scriptSig", /*optional=*/true, "",
845
0
                {
846
0
                    {RPCResult::Type::STR, "asm", "Disassembly of the final signature script"},
847
0
                    {RPCResult::Type::STR_HEX, "hex", "The raw final signature script bytes, hex-encoded"},
848
0
                }},
849
0
                {RPCResult::Type::ARR, "final_scriptwitness", /*optional=*/true, "",
850
0
                {
851
0
                    {RPCResult::Type::STR_HEX, "", "hex-encoded witness data (if any)"},
852
0
                }},
853
0
                {RPCResult::Type::OBJ_DYN, "ripemd160_preimages", /*optional=*/ true, "",
854
0
                {
855
0
                    {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
856
0
                }},
857
0
                {RPCResult::Type::OBJ_DYN, "sha256_preimages", /*optional=*/ true, "",
858
0
                {
859
0
                    {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
860
0
                }},
861
0
                {RPCResult::Type::OBJ_DYN, "hash160_preimages", /*optional=*/ true, "",
862
0
                {
863
0
                    {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
864
0
                }},
865
0
                {RPCResult::Type::OBJ_DYN, "hash256_preimages", /*optional=*/ true, "",
866
0
                {
867
0
                    {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
868
0
                }},
869
0
                {RPCResult::Type::STR_HEX, "previous_txid", /*optional=*/true, "TXID of the transaction containing the output being spent by this input"},
870
0
                {RPCResult::Type::NUM, "previous_vout", /*optional=*/true, "Index of the output being spent"},
871
0
                {RPCResult::Type::NUM, "sequence", /*optional=*/true, "Sequence number for this input"},
872
0
                {RPCResult::Type::NUM, "time_locktime", /*optional=*/true, "Time-based locktime required for this input"},
873
0
                {RPCResult::Type::NUM, "height_locktime", /*optional=*/true, "Height-based locktime required for this input"},
874
0
                {RPCResult::Type::STR_HEX, "taproot_key_path_sig", /*optional=*/ true, "hex-encoded signature for the Taproot key path spend"},
875
0
                {RPCResult::Type::ARR, "taproot_script_path_sigs", /*optional=*/ true, "",
876
0
                {
877
0
                    {RPCResult::Type::OBJ, "signature", /*optional=*/ true, "The signature for the pubkey and leaf hash combination",
878
0
                    {
879
0
                        {RPCResult::Type::STR, "pubkey", "The x-only pubkey for this signature"},
880
0
                        {RPCResult::Type::STR, "leaf_hash", "The leaf hash for this signature"},
881
0
                        {RPCResult::Type::STR, "sig", "The signature itself"},
882
0
                    }},
883
0
                }},
884
0
                {RPCResult::Type::ARR, "taproot_scripts", /*optional=*/ true, "",
885
0
                {
886
0
                    {RPCResult::Type::OBJ, "", "",
887
0
                    {
888
0
                        {RPCResult::Type::STR_HEX, "script", "A leaf script"},
889
0
                        {RPCResult::Type::NUM, "leaf_ver", "The version number for the leaf script"},
890
0
                        {RPCResult::Type::ARR, "control_blocks", "The control blocks for this script",
891
0
                        {
892
0
                            {RPCResult::Type::STR_HEX, "control_block", "A hex-encoded control block for this script"},
893
0
                        }},
894
0
                    }},
895
0
                }},
896
0
                {RPCResult::Type::ARR, "taproot_bip32_derivs", /*optional=*/ true, "",
897
0
                {
898
0
                    {RPCResult::Type::OBJ, "", "",
899
0
                    {
900
0
                        {RPCResult::Type::STR, "pubkey", "The x-only public key this path corresponds to"},
901
0
                        {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
902
0
                        {RPCResult::Type::STR, "path", "The path"},
903
0
                        {RPCResult::Type::ARR, "leaf_hashes", "The hashes of the leaves this pubkey appears in",
904
0
                        {
905
0
                            {RPCResult::Type::STR_HEX, "hash", "The hash of a leaf this pubkey appears in"},
906
0
                        }},
907
0
                    }},
908
0
                }},
909
0
                {RPCResult::Type::STR_HEX, "taproot_internal_key", /*optional=*/ true, "The hex-encoded Taproot x-only internal key"},
910
0
                {RPCResult::Type::STR_HEX, "taproot_merkle_root", /*optional=*/ true, "The hex-encoded Taproot merkle root"},
911
0
                {RPCResult::Type::ARR, "musig2_participant_pubkeys", /*optional=*/true, "",
912
0
                {
913
0
                    {RPCResult::Type::OBJ, "", "",
914
0
                    {
915
0
                        {RPCResult::Type::STR_HEX, "aggregate_pubkey", "The compressed aggregate public key for which the participants create."},
916
0
                        {RPCResult::Type::ARR, "participant_pubkeys", "",
917
0
                        {
918
0
                            {RPCResult::Type::STR_HEX, "pubkey", "The compressed public keys that are aggregated for aggregate_pubkey."},
919
0
                        }},
920
0
                    }},
921
0
                }},
922
0
                {RPCResult::Type::ARR, "musig2_pubnonces", /*optional=*/true, "",
923
0
                {
924
0
                    {RPCResult::Type::OBJ, "", "",
925
0
                    {
926
0
                        {RPCResult::Type::STR_HEX, "participant_pubkey", "The compressed public key of the participant that created this pubnonce."},
927
0
                        {RPCResult::Type::STR_HEX, "aggregate_pubkey", "The compressed aggregate public key for which this pubnonce is for."},
928
0
                        {RPCResult::Type::STR_HEX, "leaf_hash", /*optional=*/true, "The hash of the leaf script that contains the aggregate pubkey being signed for. Omitted when signing for the internal key."},
929
0
                        {RPCResult::Type::STR_HEX, "pubnonce", "The public nonce itself."},
930
0
                    }},
931
0
                }},
932
0
                {RPCResult::Type::ARR, "musig2_partial_sigs", /*optional=*/true, "",
933
0
                {
934
0
                    {RPCResult::Type::OBJ, "", "",
935
0
                    {
936
0
                        {RPCResult::Type::STR_HEX, "participant_pubkey", "The compressed public key of the participant that created this partial signature."},
937
0
                        {RPCResult::Type::STR_HEX, "aggregate_pubkey", "The compressed aggregate public key for which this partial signature is for."},
938
0
                        {RPCResult::Type::STR_HEX, "leaf_hash", /*optional=*/true, "The hash of the leaf script that contains the aggregate pubkey being signed for. Omitted when signing for the internal key."},
939
0
                        {RPCResult::Type::STR_HEX, "partial_sig", "The partial signature itself."},
940
0
                    }},
941
0
                }},
942
0
                {RPCResult::Type::OBJ_DYN, "unknown", /*optional=*/ true, "The unknown input fields",
943
0
                {
944
0
                    {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
945
0
                }},
946
0
                {RPCResult::Type::ARR, "proprietary", /*optional=*/true, "The input proprietary map",
947
0
                {
948
0
                    {RPCResult::Type::OBJ, "", "",
949
0
                    {
950
0
                        {RPCResult::Type::STR_HEX, "identifier", "The hex string for the proprietary identifier"},
951
0
                        {RPCResult::Type::NUM, "subtype", "The number for the subtype"},
952
0
                        {RPCResult::Type::STR_HEX, "key", "The hex for the key"},
953
0
                        {RPCResult::Type::STR_HEX, "value", "The hex for the value"},
954
0
                    }},
955
0
                }},
956
0
            }},
957
0
        }
958
0
    };
959
0
    return decodepsbt_inputs;
960
0
}
961
962
const RPCResult& DecodePSBTOutputs()
963
0
{
964
0
    static const RPCResult decodepsbt_outputs{
965
0
        RPCResult::Type::ARR, "outputs", "",
966
0
        {
967
0
            {RPCResult::Type::OBJ, "", "",
968
0
            {
969
0
                {RPCResult::Type::OBJ, "redeem_script", /*optional=*/true, "",
970
0
                {
971
0
                    {RPCResult::Type::STR, "asm", "Disassembly of the redeem script"},
972
0
                    {RPCResult::Type::STR_HEX, "hex", "The raw redeem script bytes, hex-encoded"},
973
0
                    {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
974
0
                }},
975
0
                {RPCResult::Type::OBJ, "witness_script", /*optional=*/true, "",
976
0
                {
977
0
                    {RPCResult::Type::STR, "asm", "Disassembly of the witness script"},
978
0
                    {RPCResult::Type::STR_HEX, "hex", "The raw witness script bytes, hex-encoded"},
979
0
                    {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
980
0
                }},
981
0
                {RPCResult::Type::ARR, "bip32_derivs", /*optional=*/true, "",
982
0
                {
983
0
                    {RPCResult::Type::OBJ, "", "",
984
0
                    {
985
0
                        {RPCResult::Type::STR, "pubkey", "The public key this path corresponds to"},
986
0
                        {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
987
0
                        {RPCResult::Type::STR, "path", "The path"},
988
0
                    }},
989
0
                }},
990
0
                {RPCResult::Type::NUM, "amount", /* optional=*/ true, "The amount (nValue) for this output"},
991
0
                {RPCResult::Type::OBJ, "script", /* optional=*/ true, "The output script (scriptPubKey) for this output",
992
0
                    ElideGroup(ScriptPubKeyDoc(), "The layout is the same as the output of scriptPubKeys in decoderawtransaction."),
993
0
                },
994
0
                {RPCResult::Type::STR_HEX, "taproot_internal_key", /*optional=*/ true, "The hex-encoded Taproot x-only internal key"},
995
0
                {RPCResult::Type::ARR, "taproot_tree", /*optional=*/ true, "The tuples that make up the Taproot tree, in depth first search order",
996
0
                {
997
0
                    {RPCResult::Type::OBJ, "tuple", /*optional=*/ true, "A single leaf script in the taproot tree",
998
0
                    {
999
0
                        {RPCResult::Type::NUM, "depth", "The depth of this element in the tree"},
1000
0
                        {RPCResult::Type::NUM, "leaf_ver", "The version of this leaf"},
1001
0
                        {RPCResult::Type::STR, "script", "The hex-encoded script itself"},
1002
0
                    }},
1003
0
                }},
1004
0
                {RPCResult::Type::ARR, "taproot_bip32_derivs", /*optional=*/ true, "",
1005
0
                {
1006
0
                    {RPCResult::Type::OBJ, "", "",
1007
0
                    {
1008
0
                        {RPCResult::Type::STR, "pubkey", "The x-only public key this path corresponds to"},
1009
0
                        {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
1010
0
                        {RPCResult::Type::STR, "path", "The path"},
1011
0
                        {RPCResult::Type::ARR, "leaf_hashes", "The hashes of the leaves this pubkey appears in",
1012
0
                        {
1013
0
                            {RPCResult::Type::STR_HEX, "hash", "The hash of a leaf this pubkey appears in"},
1014
0
                        }},
1015
0
                    }},
1016
0
                }},
1017
0
                {RPCResult::Type::ARR, "musig2_participant_pubkeys", /*optional=*/true, "",
1018
0
                {
1019
0
                    {RPCResult::Type::OBJ, "", "",
1020
0
                    {
1021
0
                        {RPCResult::Type::STR_HEX, "aggregate_pubkey", "The compressed aggregate public key for which the participants create."},
1022
0
                        {RPCResult::Type::ARR, "participant_pubkeys", "",
1023
0
                        {
1024
0
                            {RPCResult::Type::STR_HEX, "pubkey", "The compressed public keys that are aggregated for aggregate_pubkey."},
1025
0
                        }},
1026
0
                    }},
1027
0
                }},
1028
0
                {RPCResult::Type::OBJ_DYN, "unknown", /*optional=*/true, "The unknown output fields",
1029
0
                {
1030
0
                    {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
1031
0
                }},
1032
0
                {RPCResult::Type::ARR, "proprietary", /*optional=*/true, "The output proprietary map",
1033
0
                {
1034
0
                    {RPCResult::Type::OBJ, "", "",
1035
0
                    {
1036
0
                        {RPCResult::Type::STR_HEX, "identifier", "The hex string for the proprietary identifier"},
1037
0
                        {RPCResult::Type::NUM, "subtype", "The number for the subtype"},
1038
0
                        {RPCResult::Type::STR_HEX, "key", "The hex for the key"},
1039
0
                        {RPCResult::Type::STR_HEX, "value", "The hex for the value"},
1040
0
                    }},
1041
0
                }},
1042
0
            }},
1043
0
        }
1044
0
    };
1045
0
    return decodepsbt_outputs;
1046
0
}
1047
1048
static RPCMethod decodepsbt()
1049
0
{
1050
0
    return RPCMethod{
1051
0
        "decodepsbt",
1052
0
        "Return a JSON object representing the serialized, base64-encoded partially signed Bitcoin transaction.",
1053
0
                {
1054
0
                    {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "The PSBT base64 string"},
1055
0
                },
1056
0
                RPCResult{
1057
0
                    RPCResult::Type::OBJ, "", "",
1058
0
                    {
1059
0
                        {RPCResult::Type::OBJ, "tx", /*optional=*/true, "The decoded network-serialized unsigned transaction.",
1060
0
                            TxDoc({.elision_mode = ElisionMode::WithSummary, .elision_summary = "The layout is the same as the output of decoderawtransaction."})
1061
0
                        },
1062
0
                        {RPCResult::Type::ARR, "global_xpubs", "",
1063
0
                        {
1064
0
                            {RPCResult::Type::OBJ, "", "",
1065
0
                            {
1066
0
                                {RPCResult::Type::STR, "xpub", "The extended public key this path corresponds to"},
1067
0
                                {RPCResult::Type::STR_HEX, "master_fingerprint", "The fingerprint of the master key"},
1068
0
                                {RPCResult::Type::STR, "path", "The path"},
1069
0
                            }},
1070
0
                        }},
1071
0
                        {RPCResult::Type::NUM, "tx_version", /* optional */ true, "The version number of the unsigned transaction. Not to be confused with PSBT version"},
1072
0
                        {RPCResult::Type::NUM, "fallback_locktime", /* optional */ true, "The locktime to fallback to if no inputs specify a required locktime."},
1073
0
                        {RPCResult::Type::NUM, "input_count", /* optional */ true, "The number of inputs in this psbt"},
1074
0
                        {RPCResult::Type::NUM, "output_count", /* optional */ true, "The number of outputs in this psbt."},
1075
0
                        {RPCResult::Type::BOOL, "inputs_modifiable", /* optional */ true, "Whether inputs can be modified"},
1076
0
                        {RPCResult::Type::BOOL, "outputs_modifiable", /* optional */ true, "Whether outputs can be modified"},
1077
0
                        {RPCResult::Type::BOOL, "has_sighash_single", /* optional */ true, "Whether this PSBT has SIGHASH_SINGLE inputs"},
1078
0
                        {RPCResult::Type::NUM, "psbt_version", /* optional */ true, "The PSBT version number. Not to be confused with the unsigned transaction version"},
1079
0
                        {RPCResult::Type::ARR, "proprietary", "The global proprietary map",
1080
0
                        {
1081
0
                            {RPCResult::Type::OBJ, "", "",
1082
0
                            {
1083
0
                                {RPCResult::Type::STR_HEX, "identifier", "The hex string for the proprietary identifier"},
1084
0
                                {RPCResult::Type::NUM, "subtype", "The number for the subtype"},
1085
0
                                {RPCResult::Type::STR_HEX, "key", "The hex for the key"},
1086
0
                                {RPCResult::Type::STR_HEX, "value", "The hex for the value"},
1087
0
                            }},
1088
0
                        }},
1089
0
                        {RPCResult::Type::OBJ_DYN, "unknown", "The unknown global fields",
1090
0
                        {
1091
0
                             {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
1092
0
                        }},
1093
0
                        DecodePSBTInputs(),
1094
0
                        DecodePSBTOutputs(),
1095
0
                        {RPCResult::Type::STR_AMOUNT, "fee", /*optional=*/true, "The transaction fee paid if all UTXOs slots in the PSBT have been filled."},
1096
0
                    }
1097
0
                },
1098
0
                RPCExamples{
1099
0
                    HelpExampleCli("decodepsbt", "\"psbt\"")
1100
0
                },
1101
0
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
1102
0
{
1103
    // Unserialize the transactions
1104
0
    util::Result<PartiallySignedTransaction> psbt_res = DecodeBase64PSBT(request.params[0].get_str());
1105
0
    if (!psbt_res) {
1106
0
        throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", util::ErrorString(psbt_res).original));
Line
Count
Source
1172
0
#define strprintf tfm::format
1107
0
    }
1108
0
    PartiallySignedTransaction psbtx = *psbt_res;
1109
1110
0
    UniValue result(UniValue::VOBJ);
1111
1112
0
    if (psbtx.GetVersion() < 2) {
1113
        // Add the decoded tx
1114
0
        UniValue tx_univ(UniValue::VOBJ);
1115
0
        TxToUniv(CTransaction(*CHECK_NONFATAL(psbtx.GetUnsignedTx())), /*block_hash=*/uint256(), /*entry=*/tx_univ, /*include_hex=*/false);
Line
Count
Source
113
0
    inline_check_non_fatal(condition, std::source_location::current(), #condition)
1116
0
        result.pushKV("tx", std::move(tx_univ));
1117
0
    }
1118
1119
    // Add the global xpubs
1120
0
    UniValue global_xpubs(UniValue::VARR);
1121
0
    for (std::pair<KeyOriginInfo, std::set<CExtPubKey>> xpub_pair : psbtx.m_xpubs) {
1122
0
        for (auto& xpub : xpub_pair.second) {
1123
0
            std::vector<unsigned char> ser_xpub;
1124
0
            ser_xpub.assign(BIP32_EXTKEY_WITH_VERSION_SIZE, 0);
1125
0
            xpub.EncodeWithVersion(ser_xpub.data());
1126
1127
0
            UniValue keypath(UniValue::VOBJ);
1128
0
            keypath.pushKV("xpub", EncodeBase58Check(ser_xpub));
1129
0
            keypath.pushKV("master_fingerprint", HexStr(xpub_pair.first.fingerprint));
1130
0
            keypath.pushKV("path", WriteHDKeypath(xpub_pair.first.path));
1131
0
            global_xpubs.push_back(std::move(keypath));
1132
0
        }
1133
0
    }
1134
0
    result.pushKV("global_xpubs", std::move(global_xpubs));
1135
1136
    // Add PSBTv2 stuff
1137
0
    if (psbtx.GetVersion() >= 2) {
1138
0
        result.pushKV("tx_version", psbtx.tx_version);
1139
0
        if (psbtx.fallback_locktime.has_value()) {
1140
0
            result.pushKV("fallback_locktime", static_cast<uint64_t>(*psbtx.fallback_locktime));
1141
0
        }
1142
0
        result.pushKV("input_count", (uint64_t)psbtx.inputs.size());
1143
0
        result.pushKV("output_count", (uint64_t)psbtx.outputs.size());
1144
0
        if (psbtx.m_tx_modifiable.has_value()) {
1145
0
            result.pushKV("inputs_modifiable", psbtx.m_tx_modifiable->test(0));
1146
0
            result.pushKV("outputs_modifiable", psbtx.m_tx_modifiable->test(1));
1147
0
            result.pushKV("has_sighash_single", psbtx.m_tx_modifiable->test(2));
1148
0
        }
1149
0
    }
1150
1151
    // PSBT version
1152
0
    result.pushKV("psbt_version", psbtx.GetVersion());
1153
1154
    // Proprietary
1155
0
    UniValue proprietary(UniValue::VARR);
1156
0
    for (const auto& entry : psbtx.m_proprietary) {
1157
0
        UniValue this_prop(UniValue::VOBJ);
1158
0
        this_prop.pushKV("identifier", HexStr(entry.identifier));
1159
0
        this_prop.pushKV("subtype", entry.subtype);
1160
0
        this_prop.pushKV("key", HexStr(entry.key));
1161
0
        this_prop.pushKV("value", HexStr(entry.value));
1162
0
        proprietary.push_back(std::move(this_prop));
1163
0
    }
1164
0
    result.pushKV("proprietary", std::move(proprietary));
1165
1166
    // Unknown data
1167
0
    UniValue unknowns(UniValue::VOBJ);
1168
0
    for (auto entry : psbtx.unknown) {
1169
0
        unknowns.pushKV(HexStr(entry.first), HexStr(entry.second));
1170
0
    }
1171
0
    result.pushKV("unknown", std::move(unknowns));
1172
1173
    // inputs
1174
0
    CAmount total_in = 0;
1175
0
    bool have_all_utxos = true;
1176
0
    UniValue inputs(UniValue::VARR);
1177
0
    for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {
1178
0
        const PSBTInput& input = psbtx.inputs[i];
1179
0
        UniValue in(UniValue::VOBJ);
1180
        // UTXOs
1181
0
        bool have_a_utxo = false;
1182
0
        CTxOut txout;
1183
0
        if (!input.witness_utxo.IsNull()) {
1184
0
            txout = input.witness_utxo;
1185
1186
0
            UniValue o(UniValue::VOBJ);
1187
0
            ScriptToUniv(txout.scriptPubKey, /*out=*/o, /*include_hex=*/true, /*include_address=*/true);
1188
1189
0
            UniValue out(UniValue::VOBJ);
1190
0
            out.pushKV("amount", ValueFromAmount(txout.nValue));
1191
0
            out.pushKV("scriptPubKey", std::move(o));
1192
1193
0
            in.pushKV("witness_utxo", std::move(out));
1194
1195
0
            have_a_utxo = true;
1196
0
        }
1197
0
        if (input.non_witness_utxo) {
1198
0
            txout = input.non_witness_utxo->vout[input.prev_out];
1199
1200
0
            UniValue non_wit(UniValue::VOBJ);
1201
0
            TxToUniv(*input.non_witness_utxo, /*block_hash=*/uint256(), /*entry=*/non_wit, /*include_hex=*/false);
1202
0
            in.pushKV("non_witness_utxo", std::move(non_wit));
1203
1204
0
            have_a_utxo = true;
1205
0
        }
1206
0
        if (have_a_utxo) {
1207
0
            if (MoneyRange(txout.nValue) && MoneyRange(total_in + txout.nValue)) {
1208
0
                total_in += txout.nValue;
1209
0
            } else {
1210
                // Hack to just not show fee later
1211
0
                have_all_utxos = false;
1212
0
            }
1213
0
        } else {
1214
0
            have_all_utxos = false;
1215
0
        }
1216
1217
        // Partial sigs
1218
0
        if (!input.partial_sigs.empty()) {
1219
0
            UniValue partial_sigs(UniValue::VOBJ);
1220
0
            for (const auto& sig : input.partial_sigs) {
1221
0
                partial_sigs.pushKV(HexStr(sig.second.first), HexStr(sig.second.second));
1222
0
            }
1223
0
            in.pushKV("partial_signatures", std::move(partial_sigs));
1224
0
        }
1225
1226
        // Sighash
1227
0
        if (input.sighash_type != std::nullopt) {
1228
0
            in.pushKV("sighash", SighashToStr((unsigned char)*input.sighash_type));
1229
0
        }
1230
1231
        // Redeem script and witness script
1232
0
        if (!input.redeem_script.empty()) {
1233
0
            UniValue r(UniValue::VOBJ);
1234
0
            ScriptToUniv(input.redeem_script, /*out=*/r);
1235
0
            in.pushKV("redeem_script", std::move(r));
1236
0
        }
1237
0
        if (!input.witness_script.empty()) {
1238
0
            UniValue r(UniValue::VOBJ);
1239
0
            ScriptToUniv(input.witness_script, /*out=*/r);
1240
0
            in.pushKV("witness_script", std::move(r));
1241
0
        }
1242
1243
        // keypaths
1244
0
        if (!input.hd_keypaths.empty()) {
1245
0
            UniValue keypaths(UniValue::VARR);
1246
0
            for (auto entry : input.hd_keypaths) {
1247
0
                UniValue keypath(UniValue::VOBJ);
1248
0
                keypath.pushKV("pubkey", HexStr(entry.first));
1249
1250
0
                keypath.pushKV("master_fingerprint", strprintf("%08x", ReadBE32(entry.second.fingerprint.data())));
Line
Count
Source
1172
0
#define strprintf tfm::format
1251
0
                keypath.pushKV("path", WriteHDKeypath(entry.second.path));
1252
0
                keypaths.push_back(std::move(keypath));
1253
0
            }
1254
0
            in.pushKV("bip32_derivs", std::move(keypaths));
1255
0
        }
1256
1257
        // Final scriptSig and scriptwitness
1258
0
        if (!input.final_script_sig.empty()) {
1259
0
            UniValue scriptsig(UniValue::VOBJ);
1260
0
            scriptsig.pushKV("asm", ScriptToAsmStr(input.final_script_sig, true));
1261
0
            scriptsig.pushKV("hex", HexStr(input.final_script_sig));
1262
0
            in.pushKV("final_scriptSig", std::move(scriptsig));
1263
0
        }
1264
0
        if (!input.final_script_witness.IsNull()) {
1265
0
            UniValue txinwitness(UniValue::VARR);
1266
0
            for (const auto& item : input.final_script_witness.stack) {
1267
0
                txinwitness.push_back(HexStr(item));
1268
0
            }
1269
0
            in.pushKV("final_scriptwitness", std::move(txinwitness));
1270
0
        }
1271
1272
        // Ripemd160 hash preimages
1273
0
        if (!input.ripemd160_preimages.empty()) {
1274
0
            UniValue ripemd160_preimages(UniValue::VOBJ);
1275
0
            for (const auto& [hash, preimage] : input.ripemd160_preimages) {
1276
0
                ripemd160_preimages.pushKV(HexStr(hash), HexStr(preimage));
1277
0
            }
1278
0
            in.pushKV("ripemd160_preimages", std::move(ripemd160_preimages));
1279
0
        }
1280
1281
        // Sha256 hash preimages
1282
0
        if (!input.sha256_preimages.empty()) {
1283
0
            UniValue sha256_preimages(UniValue::VOBJ);
1284
0
            for (const auto& [hash, preimage] : input.sha256_preimages) {
1285
0
                sha256_preimages.pushKV(HexStr(hash), HexStr(preimage));
1286
0
            }
1287
0
            in.pushKV("sha256_preimages", std::move(sha256_preimages));
1288
0
        }
1289
1290
        // Hash160 hash preimages
1291
0
        if (!input.hash160_preimages.empty()) {
1292
0
            UniValue hash160_preimages(UniValue::VOBJ);
1293
0
            for (const auto& [hash, preimage] : input.hash160_preimages) {
1294
0
                hash160_preimages.pushKV(HexStr(hash), HexStr(preimage));
1295
0
            }
1296
0
            in.pushKV("hash160_preimages", std::move(hash160_preimages));
1297
0
        }
1298
1299
        // Hash256 hash preimages
1300
0
        if (!input.hash256_preimages.empty()) {
1301
0
            UniValue hash256_preimages(UniValue::VOBJ);
1302
0
            for (const auto& [hash, preimage] : input.hash256_preimages) {
1303
0
                hash256_preimages.pushKV(HexStr(hash), HexStr(preimage));
1304
0
            }
1305
0
            in.pushKV("hash256_preimages", std::move(hash256_preimages));
1306
0
        }
1307
1308
        // PSBTv2
1309
0
        if (psbtx.GetVersion() >= 2) {
1310
0
            in.pushKV("previous_txid", input.prev_txid.GetHex());
1311
0
            in.pushKV("previous_vout", static_cast<uint64_t>(input.prev_out));
1312
0
            if (input.sequence.has_value()) {
1313
0
                in.pushKV("sequence", static_cast<uint64_t>(*input.sequence));
1314
0
            }
1315
0
            if (input.time_locktime.has_value()) {
1316
0
                in.pushKV("time_locktime", static_cast<uint64_t>(*input.time_locktime));
1317
0
            }
1318
0
            if (input.height_locktime.has_value()) {
1319
0
                in.pushKV("height_locktime", static_cast<uint64_t>(*input.height_locktime));
1320
0
            }
1321
0
        }
1322
1323
        // Taproot key path signature
1324
0
        if (!input.m_tap_key_sig.empty()) {
1325
0
            in.pushKV("taproot_key_path_sig", HexStr(input.m_tap_key_sig));
1326
0
        }
1327
1328
        // Taproot script path signatures
1329
0
        if (!input.m_tap_script_sigs.empty()) {
1330
0
            UniValue script_sigs(UniValue::VARR);
1331
0
            for (const auto& [pubkey_leaf, sig] : input.m_tap_script_sigs) {
1332
0
                const auto& [xonly, leaf_hash] = pubkey_leaf;
1333
0
                UniValue sigobj(UniValue::VOBJ);
1334
0
                sigobj.pushKV("pubkey", HexStr(xonly));
1335
0
                sigobj.pushKV("leaf_hash", HexStr(leaf_hash));
1336
0
                sigobj.pushKV("sig", HexStr(sig));
1337
0
                script_sigs.push_back(std::move(sigobj));
1338
0
            }
1339
0
            in.pushKV("taproot_script_path_sigs", std::move(script_sigs));
1340
0
        }
1341
1342
        // Taproot leaf scripts
1343
0
        if (!input.m_tap_scripts.empty()) {
1344
0
            UniValue tap_scripts(UniValue::VARR);
1345
0
            for (const auto& [leaf, control_blocks] : input.m_tap_scripts) {
1346
0
                const auto& [script, leaf_ver] = leaf;
1347
0
                UniValue script_info(UniValue::VOBJ);
1348
0
                script_info.pushKV("script", HexStr(script));
1349
0
                script_info.pushKV("leaf_ver", leaf_ver);
1350
0
                UniValue control_blocks_univ(UniValue::VARR);
1351
0
                for (const auto& control_block : control_blocks) {
1352
0
                    control_blocks_univ.push_back(HexStr(control_block));
1353
0
                }
1354
0
                script_info.pushKV("control_blocks", std::move(control_blocks_univ));
1355
0
                tap_scripts.push_back(std::move(script_info));
1356
0
            }
1357
0
            in.pushKV("taproot_scripts", std::move(tap_scripts));
1358
0
        }
1359
1360
        // Taproot bip32 keypaths
1361
0
        if (!input.m_tap_bip32_paths.empty()) {
1362
0
            UniValue keypaths(UniValue::VARR);
1363
0
            for (const auto& [xonly, leaf_origin] : input.m_tap_bip32_paths) {
1364
0
                const auto& [leaf_hashes, origin] = leaf_origin;
1365
0
                UniValue path_obj(UniValue::VOBJ);
1366
0
                path_obj.pushKV("pubkey", HexStr(xonly));
1367
0
                path_obj.pushKV("master_fingerprint", strprintf("%08x", ReadBE32(origin.fingerprint.data())));
Line
Count
Source
1172
0
#define strprintf tfm::format
1368
0
                path_obj.pushKV("path", WriteHDKeypath(origin.path));
1369
0
                UniValue leaf_hashes_arr(UniValue::VARR);
1370
0
                for (const auto& leaf_hash : leaf_hashes) {
1371
0
                    leaf_hashes_arr.push_back(HexStr(leaf_hash));
1372
0
                }
1373
0
                path_obj.pushKV("leaf_hashes", std::move(leaf_hashes_arr));
1374
0
                keypaths.push_back(std::move(path_obj));
1375
0
            }
1376
0
            in.pushKV("taproot_bip32_derivs", std::move(keypaths));
1377
0
        }
1378
1379
        // Taproot internal key
1380
0
        if (!input.m_tap_internal_key.IsNull()) {
1381
0
            in.pushKV("taproot_internal_key", HexStr(input.m_tap_internal_key));
1382
0
        }
1383
1384
        // Write taproot merkle root
1385
0
        if (!input.m_tap_merkle_root.IsNull()) {
1386
0
            in.pushKV("taproot_merkle_root", HexStr(input.m_tap_merkle_root));
1387
0
        }
1388
1389
        // Write MuSig2 fields
1390
0
        if (!input.m_musig2_participants.empty()) {
1391
0
            UniValue musig_pubkeys(UniValue::VARR);
1392
0
            for (const auto& [agg, parts] : input.m_musig2_participants) {
1393
0
                UniValue musig_part(UniValue::VOBJ);
1394
0
                musig_part.pushKV("aggregate_pubkey", HexStr(agg));
1395
0
                UniValue part_pubkeys(UniValue::VARR);
1396
0
                for (const auto& pub : parts) {
1397
0
                    part_pubkeys.push_back(HexStr(pub));
1398
0
                }
1399
0
                musig_part.pushKV("participant_pubkeys", part_pubkeys);
1400
0
                musig_pubkeys.push_back(musig_part);
1401
0
            }
1402
0
            in.pushKV("musig2_participant_pubkeys", musig_pubkeys);
1403
0
        }
1404
0
        if (!input.m_musig2_pubnonces.empty()) {
1405
0
            UniValue musig_pubnonces(UniValue::VARR);
1406
0
            for (const auto& [agg_lh, part_pubnonce] : input.m_musig2_pubnonces) {
1407
0
                const auto& [agg, lh] = agg_lh;
1408
0
                for (const auto& [part, pubnonce] : part_pubnonce) {
1409
0
                    UniValue info(UniValue::VOBJ);
1410
0
                    info.pushKV("participant_pubkey", HexStr(part));
1411
0
                    info.pushKV("aggregate_pubkey", HexStr(agg));
1412
0
                    if (!lh.IsNull()) info.pushKV("leaf_hash", HexStr(lh));
1413
0
                    info.pushKV("pubnonce", HexStr(pubnonce));
1414
0
                    musig_pubnonces.push_back(info);
1415
0
                }
1416
0
            }
1417
0
            in.pushKV("musig2_pubnonces", musig_pubnonces);
1418
0
        }
1419
0
        if (!input.m_musig2_partial_sigs.empty()) {
1420
0
            UniValue musig_partial_sigs(UniValue::VARR);
1421
0
            for (const auto& [agg_lh, part_psig] : input.m_musig2_partial_sigs) {
1422
0
                const auto& [agg, lh] = agg_lh;
1423
0
                for (const auto& [part, psig] : part_psig) {
1424
0
                    UniValue info(UniValue::VOBJ);
1425
0
                    info.pushKV("participant_pubkey", HexStr(part));
1426
0
                    info.pushKV("aggregate_pubkey", HexStr(agg));
1427
0
                    if (!lh.IsNull()) info.pushKV("leaf_hash", HexStr(lh));
1428
0
                    info.pushKV("partial_sig", HexStr(psig));
1429
0
                    musig_partial_sigs.push_back(info);
1430
0
                }
1431
0
            }
1432
0
            in.pushKV("musig2_partial_sigs", musig_partial_sigs);
1433
0
        }
1434
1435
        // Proprietary
1436
0
        if (!input.m_proprietary.empty()) {
1437
0
            UniValue proprietary(UniValue::VARR);
1438
0
            for (const auto& entry : input.m_proprietary) {
1439
0
                UniValue this_prop(UniValue::VOBJ);
1440
0
                this_prop.pushKV("identifier", HexStr(entry.identifier));
1441
0
                this_prop.pushKV("subtype", entry.subtype);
1442
0
                this_prop.pushKV("key", HexStr(entry.key));
1443
0
                this_prop.pushKV("value", HexStr(entry.value));
1444
0
                proprietary.push_back(std::move(this_prop));
1445
0
            }
1446
0
            in.pushKV("proprietary", std::move(proprietary));
1447
0
        }
1448
1449
        // Unknown data
1450
0
        if (input.unknown.size() > 0) {
1451
0
            UniValue unknowns(UniValue::VOBJ);
1452
0
            for (auto entry : input.unknown) {
1453
0
                unknowns.pushKV(HexStr(entry.first), HexStr(entry.second));
1454
0
            }
1455
0
            in.pushKV("unknown", std::move(unknowns));
1456
0
        }
1457
1458
0
        inputs.push_back(std::move(in));
1459
0
    }
1460
0
    result.pushKV("inputs", std::move(inputs));
1461
1462
    // outputs
1463
0
    CAmount output_value = 0;
1464
0
    UniValue outputs(UniValue::VARR);
1465
0
    for (unsigned int i = 0; i < psbtx.outputs.size(); ++i) {
1466
0
        const PSBTOutput& output = psbtx.outputs[i];
1467
0
        UniValue out(UniValue::VOBJ);
1468
        // Redeem script and witness script
1469
0
        if (!output.redeem_script.empty()) {
1470
0
            UniValue r(UniValue::VOBJ);
1471
0
            ScriptToUniv(output.redeem_script, /*out=*/r);
1472
0
            out.pushKV("redeem_script", std::move(r));
1473
0
        }
1474
0
        if (!output.witness_script.empty()) {
1475
0
            UniValue r(UniValue::VOBJ);
1476
0
            ScriptToUniv(output.witness_script, /*out=*/r);
1477
0
            out.pushKV("witness_script", std::move(r));
1478
0
        }
1479
1480
        // keypaths
1481
0
        if (!output.hd_keypaths.empty()) {
1482
0
            UniValue keypaths(UniValue::VARR);
1483
0
            for (auto entry : output.hd_keypaths) {
1484
0
                UniValue keypath(UniValue::VOBJ);
1485
0
                keypath.pushKV("pubkey", HexStr(entry.first));
1486
0
                keypath.pushKV("master_fingerprint", strprintf("%08x", ReadBE32(entry.second.fingerprint.data())));
Line
Count
Source
1172
0
#define strprintf tfm::format
1487
0
                keypath.pushKV("path", WriteHDKeypath(entry.second.path));
1488
0
                keypaths.push_back(std::move(keypath));
1489
0
            }
1490
0
            out.pushKV("bip32_derivs", std::move(keypaths));
1491
0
        }
1492
1493
        // PSBTv2 stuff
1494
0
        if (psbtx.GetVersion() >= 2) {
1495
0
            out.pushKV("amount", ValueFromAmount(output.amount));
1496
0
            UniValue spk(UniValue::VOBJ);
1497
0
            ScriptToUniv(output.script, spk, /*include_hex=*/true, /*include_address=*/true);
1498
0
            out.pushKV("script", spk);
1499
0
        }
1500
1501
        // Taproot internal key
1502
0
        if (!output.m_tap_internal_key.IsNull()) {
1503
0
            out.pushKV("taproot_internal_key", HexStr(output.m_tap_internal_key));
1504
0
        }
1505
1506
        // Taproot tree
1507
0
        if (!output.m_tap_tree.empty()) {
1508
0
            UniValue tree(UniValue::VARR);
1509
0
            for (const auto& [depth, leaf_ver, script] : output.m_tap_tree) {
1510
0
                UniValue elem(UniValue::VOBJ);
1511
0
                elem.pushKV("depth", depth);
1512
0
                elem.pushKV("leaf_ver", leaf_ver);
1513
0
                elem.pushKV("script", HexStr(script));
1514
0
                tree.push_back(std::move(elem));
1515
0
            }
1516
0
            out.pushKV("taproot_tree", std::move(tree));
1517
0
        }
1518
1519
        // Taproot bip32 keypaths
1520
0
        if (!output.m_tap_bip32_paths.empty()) {
1521
0
            UniValue keypaths(UniValue::VARR);
1522
0
            for (const auto& [xonly, leaf_origin] : output.m_tap_bip32_paths) {
1523
0
                const auto& [leaf_hashes, origin] = leaf_origin;
1524
0
                UniValue path_obj(UniValue::VOBJ);
1525
0
                path_obj.pushKV("pubkey", HexStr(xonly));
1526
0
                path_obj.pushKV("master_fingerprint", strprintf("%08x", ReadBE32(origin.fingerprint.data())));
Line
Count
Source
1172
0
#define strprintf tfm::format
1527
0
                path_obj.pushKV("path", WriteHDKeypath(origin.path));
1528
0
                UniValue leaf_hashes_arr(UniValue::VARR);
1529
0
                for (const auto& leaf_hash : leaf_hashes) {
1530
0
                    leaf_hashes_arr.push_back(HexStr(leaf_hash));
1531
0
                }
1532
0
                path_obj.pushKV("leaf_hashes", std::move(leaf_hashes_arr));
1533
0
                keypaths.push_back(std::move(path_obj));
1534
0
            }
1535
0
            out.pushKV("taproot_bip32_derivs", std::move(keypaths));
1536
0
        }
1537
1538
        // Write MuSig2 fields
1539
0
        if (!output.m_musig2_participants.empty()) {
1540
0
            UniValue musig_pubkeys(UniValue::VARR);
1541
0
            for (const auto& [agg, parts] : output.m_musig2_participants) {
1542
0
                UniValue musig_part(UniValue::VOBJ);
1543
0
                musig_part.pushKV("aggregate_pubkey", HexStr(agg));
1544
0
                UniValue part_pubkeys(UniValue::VARR);
1545
0
                for (const auto& pub : parts) {
1546
0
                    part_pubkeys.push_back(HexStr(pub));
1547
0
                }
1548
0
                musig_part.pushKV("participant_pubkeys", part_pubkeys);
1549
0
                musig_pubkeys.push_back(musig_part);
1550
0
            }
1551
0
            out.pushKV("musig2_participant_pubkeys", musig_pubkeys);
1552
0
        }
1553
1554
        // Proprietary
1555
0
        if (!output.m_proprietary.empty()) {
1556
0
            UniValue proprietary(UniValue::VARR);
1557
0
            for (const auto& entry : output.m_proprietary) {
1558
0
                UniValue this_prop(UniValue::VOBJ);
1559
0
                this_prop.pushKV("identifier", HexStr(entry.identifier));
1560
0
                this_prop.pushKV("subtype", entry.subtype);
1561
0
                this_prop.pushKV("key", HexStr(entry.key));
1562
0
                this_prop.pushKV("value", HexStr(entry.value));
1563
0
                proprietary.push_back(std::move(this_prop));
1564
0
            }
1565
0
            out.pushKV("proprietary", std::move(proprietary));
1566
0
        }
1567
1568
        // Unknown data
1569
0
        if (output.unknown.size() > 0) {
1570
0
            UniValue unknowns(UniValue::VOBJ);
1571
0
            for (auto entry : output.unknown) {
1572
0
                unknowns.pushKV(HexStr(entry.first), HexStr(entry.second));
1573
0
            }
1574
0
            out.pushKV("unknown", std::move(unknowns));
1575
0
        }
1576
1577
0
        outputs.push_back(std::move(out));
1578
1579
        // Fee calculation
1580
0
        if (MoneyRange(output.amount) && MoneyRange(output_value + output.amount)) {
1581
0
            output_value += output.amount;
1582
0
        } else {
1583
            // Hack to just not show fee later
1584
0
            have_all_utxos = false;
1585
0
        }
1586
0
    }
1587
0
    result.pushKV("outputs", std::move(outputs));
1588
0
    if (have_all_utxos) {
1589
0
        result.pushKV("fee", ValueFromAmount(total_in - output_value));
1590
0
    }
1591
1592
0
    return result;
1593
0
},
1594
0
    };
1595
0
}
1596
1597
static RPCMethod combinepsbt()
1598
0
{
1599
0
    return RPCMethod{
1600
0
        "combinepsbt",
1601
0
        "Combine multiple partially signed Bitcoin transactions into one transaction.\n"
1602
0
                "Implements the Combiner role.\n",
1603
0
                {
1604
0
                    {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The base64 strings of partially signed transactions",
1605
0
                        {
1606
0
                            {"psbt", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A base64 string of a PSBT"},
1607
0
                        },
1608
0
                        },
1609
0
                },
1610
0
                RPCResult{
1611
0
                    RPCResult::Type::STR, "", "The base64-encoded partially signed transaction"
1612
0
                },
1613
0
                RPCExamples{
1614
0
                    HelpExampleCli("combinepsbt", R"('["mybase64_1", "mybase64_2", "mybase64_3"]')")
1615
0
                },
1616
0
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
1617
0
{
1618
    // Unserialize the transactions
1619
0
    std::vector<PartiallySignedTransaction> psbtxs;
1620
0
    UniValue txs = request.params[0].get_array();
1621
0
    if (txs.empty()) {
1622
0
        throw JSONRPCError(RPC_INVALID_PARAMETER, "Parameter 'txs' cannot be empty");
1623
0
    }
1624
0
    for (unsigned int i = 0; i < txs.size(); ++i) {
1625
0
        util::Result<PartiallySignedTransaction> psbt_res = DecodeBase64PSBT(txs[i].get_str());
1626
0
        if (!psbt_res) {
1627
0
            throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", util::ErrorString(psbt_res).original));
Line
Count
Source
1172
0
#define strprintf tfm::format
1628
0
        }
1629
0
        psbtxs.push_back(*psbt_res);
1630
0
    }
1631
1632
0
    std::optional<PartiallySignedTransaction> merged_psbt = CombinePSBTs(psbtxs);
1633
0
    if (!merged_psbt) {
1634
0
        throw JSONRPCError(RPC_INVALID_PARAMETER, "PSBTs not compatible (different transactions)");
1635
0
    }
1636
1637
0
    DataStream ssTx{};
1638
0
    ssTx << *merged_psbt;
1639
0
    return EncodeBase64(ssTx);
1640
0
},
1641
0
    };
1642
0
}
1643
1644
static RPCMethod finalizepsbt()
1645
0
{
1646
0
    return RPCMethod{"finalizepsbt",
1647
0
                "Finalize the inputs of a PSBT. If the transaction is fully signed, it will produce a\n"
1648
0
                "network serialized transaction which can be broadcast with sendrawtransaction. Otherwise a PSBT will be\n"
1649
0
                "created which has the final_scriptSig and final_scriptwitness fields filled for inputs that are complete.\n"
1650
0
                "Implements the Finalizer and Extractor roles.\n",
1651
0
                {
1652
0
                    {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"},
1653
0
                    {"extract", RPCArg::Type::BOOL, RPCArg::Default{true}, "If true and the transaction is complete,\n"
1654
0
            "                             extract and return the complete transaction in normal network serialization instead of the PSBT."},
1655
0
                },
1656
0
                RPCResult{
1657
0
                    RPCResult::Type::OBJ, "", "",
1658
0
                    {
1659
0
                        {RPCResult::Type::STR, "psbt", /*optional=*/true, "The base64-encoded partially signed transaction if not extracted"},
1660
0
                        {RPCResult::Type::STR_HEX, "hex", /*optional=*/true, "The hex-encoded network transaction if extracted"},
1661
0
                        {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
1662
0
                    }
1663
0
                },
1664
0
                RPCExamples{
1665
0
                    HelpExampleCli("finalizepsbt", "\"psbt\"")
1666
0
                },
1667
0
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
1668
0
{
1669
    // Unserialize the transactions
1670
0
    util::Result<PartiallySignedTransaction> psbt_res = DecodeBase64PSBT(request.params[0].get_str());
1671
0
    if (!psbt_res) {
1672
0
        throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", util::ErrorString(psbt_res).original));
Line
Count
Source
1172
0
#define strprintf tfm::format
1673
0
    }
1674
0
    PartiallySignedTransaction psbtx = *psbt_res;
1675
1676
0
    bool extract = request.params[1].isNull() || (!request.params[1].isNull() && request.params[1].get_bool());
1677
1678
0
    CMutableTransaction mtx;
1679
0
    bool complete = FinalizeAndExtractPSBT(psbtx, mtx);
1680
1681
0
    UniValue result(UniValue::VOBJ);
1682
0
    DataStream ssTx{};
1683
0
    std::string result_str;
1684
1685
0
    if (complete && extract) {
1686
0
        ssTx << TX_WITH_WITNESS(mtx);
1687
0
        result_str = HexStr(ssTx);
1688
0
        result.pushKV("hex", result_str);
1689
0
    } else {
1690
0
        ssTx << psbtx;
1691
0
        result_str = EncodeBase64(ssTx.str());
1692
0
        result.pushKV("psbt", result_str);
1693
0
    }
1694
0
    result.pushKV("complete", complete);
1695
1696
0
    return result;
1697
0
},
1698
0
    };
1699
0
}
1700
1701
static RPCMethod createpsbt()
1702
0
{
1703
0
    return RPCMethod{
1704
0
        "createpsbt",
1705
0
        "Creates a transaction in the Partially Signed Transaction format.\n"
1706
0
                "Implements the Creator role.\n"
1707
0
                "Note that the transaction's inputs are not signed, and\n"
1708
0
                "it is not stored in the wallet or transmitted to the network.\n",
1709
0
                Cat<std::vector<RPCArg>>(
1710
0
                    CreateTxDoc(),
1711
0
                    {
1712
0
                        {"psbt_version", RPCArg::Type::NUM, RPCArg::Default{2}, "The PSBT version number to use."},
1713
0
                    }
1714
0
                ),
1715
0
                RPCResult{
1716
0
                    RPCResult::Type::STR, "", "The resulting raw transaction (base64-encoded string)"
1717
0
                },
1718
0
                RPCExamples{
1719
0
                    HelpExampleCli("createpsbt", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"address\\\":0.01}]\"")
1720
0
                },
1721
0
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
1722
0
{
1723
0
    std::optional<bool> rbf;
1724
0
    if (!request.params[3].isNull()) {
1725
0
        rbf = request.params[3].get_bool();
1726
0
    }
1727
0
    CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], rbf, self.Arg<uint32_t>("version"));
1728
1729
    // Make a blank psbt
1730
0
    uint32_t psbt_version = 2;
1731
0
    if (!request.params[5].isNull()) {
1732
0
        psbt_version = request.params[5].getInt<uint32_t>();
1733
0
    }
1734
0
    if (psbt_version != 2 && psbt_version != 0) {
1735
0
        throw JSONRPCError(RPC_INVALID_PARAMETER, "The PSBT version can only be 2 or 0");
1736
0
    }
1737
0
    PartiallySignedTransaction psbtx(rawTx, psbt_version);
1738
1739
    // Serialize the PSBT
1740
0
    DataStream ssTx{};
1741
0
    ssTx << psbtx;
1742
1743
0
    return EncodeBase64(ssTx);
1744
0
},
1745
0
    };
1746
0
}
1747
1748
static RPCMethod converttopsbt()
1749
0
{
1750
0
    return RPCMethod{
1751
0
        "converttopsbt",
1752
0
        "Converts a network serialized transaction to a PSBT. This should be used only with createrawtransaction and fundrawtransaction\n"
1753
0
                "createpsbt and walletcreatefundedpsbt should be used for new applications.\n",
1754
0
                {
1755
0
                    {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex string of a raw transaction"},
1756
0
                    {"permitsigdata", RPCArg::Type::BOOL, RPCArg::Default{false}, "If true, any signatures in the input will be discarded and conversion\n"
1757
0
                            "                              will continue. If false, RPC will fail if any signatures are present."},
1758
0
                    {"iswitness", RPCArg::Type::BOOL, RPCArg::DefaultHint{"depends on heuristic tests"}, "Whether the transaction hex is a serialized witness transaction.\n"
1759
0
                        "If iswitness is not present, heuristic tests will be used in decoding.\n"
1760
0
                        "If true, only witness deserialization will be tried.\n"
1761
0
                        "If false, only non-witness deserialization will be tried.\n"
1762
0
                        "This boolean should reflect whether the transaction has inputs\n"
1763
0
                        "(e.g. fully valid, or on-chain transactions), if known by the caller."
1764
0
                    },
1765
0
                    {"psbt_version", RPCArg::Type::NUM, RPCArg::Default{2}, "The PSBT version number to use."},
1766
0
                },
1767
0
                RPCResult{
1768
0
                    RPCResult::Type::STR, "", "The resulting raw transaction (base64-encoded string)"
1769
0
                },
1770
0
                RPCExamples{
1771
0
                            "\nCreate a transaction\n"
1772
0
                            + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"") +
1773
0
                            "\nConvert the transaction to a PSBT\n"
1774
0
                            + HelpExampleCli("converttopsbt", "\"rawtransaction\"")
1775
0
                },
1776
0
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
1777
0
{
1778
    // parse hex string from parameter
1779
0
    CMutableTransaction tx;
1780
0
    bool permitsigdata = request.params[1].isNull() ? false : request.params[1].get_bool();
1781
0
    bool witness_specified = !request.params[2].isNull();
1782
0
    bool iswitness = witness_specified ? request.params[2].get_bool() : false;
1783
0
    const bool try_witness = witness_specified ? iswitness : true;
1784
0
    const bool try_no_witness = witness_specified ? !iswitness : true;
1785
0
    if (!DecodeHexTx(tx, request.params[0].get_str(), try_no_witness, try_witness)) {
1786
0
        throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
1787
0
    }
1788
1789
    // Remove all scriptSigs and scriptWitnesses from inputs
1790
0
    for (CTxIn& input : tx.vin) {
1791
0
        if ((!input.scriptSig.empty() || !input.scriptWitness.IsNull()) && !permitsigdata) {
1792
0
            throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Inputs must not have scriptSigs and scriptWitnesses");
1793
0
        }
1794
0
        input.scriptSig.clear();
1795
0
        input.scriptWitness.SetNull();
1796
0
    }
1797
1798
    // Make a blank psbt
1799
0
    uint32_t psbt_version = 2;
1800
0
    if (!request.params[3].isNull()) {
1801
0
        psbt_version = request.params[3].getInt<uint32_t>();
1802
0
    }
1803
0
    if (psbt_version != 2 && psbt_version != 0) {
1804
0
        throw JSONRPCError(RPC_INVALID_PARAMETER, "The PSBT version can only be 2 or 0");
1805
0
    }
1806
0
    PartiallySignedTransaction psbtx(tx, psbt_version);
1807
1808
    // Serialize the PSBT
1809
0
    DataStream ssTx{};
1810
0
    ssTx << psbtx;
1811
1812
0
    return EncodeBase64(ssTx);
1813
0
},
1814
0
    };
1815
0
}
1816
1817
static RPCMethod utxoupdatepsbt()
1818
0
{
1819
0
    return RPCMethod{
1820
0
        "utxoupdatepsbt",
1821
0
        "Updates all segwit inputs and outputs in a PSBT with data from output descriptors, the UTXO set, txindex, or the mempool.\n",
1822
0
            {
1823
0
                {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"},
1824
0
                {"descriptors", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "An array of either strings or objects", {
1825
0
                    {"", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "An output descriptor"},
1826
0
                    {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "An object with an output descriptor and extra information", {
1827
0
                         {"desc", RPCArg::Type::STR, RPCArg::Optional::NO, "An output descriptor"},
1828
0
                         {"range", RPCArg::Type::RANGE, RPCArg::Default{1000}, "Up to what index HD chains should be explored (either end or [begin,end])"},
1829
0
                    }},
1830
0
                }},
1831
0
            },
1832
0
            RPCResult {
1833
0
                    RPCResult::Type::STR, "", "The base64-encoded partially signed transaction with inputs updated"
1834
0
            },
1835
0
            RPCExamples {
1836
0
                HelpExampleCli("utxoupdatepsbt", "\"psbt\"")
1837
0
            },
1838
0
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
1839
0
{
1840
    // Parse descriptors, if any.
1841
0
    FlatSigningProvider provider;
1842
0
    if (!request.params[1].isNull()) {
1843
0
        auto descs = request.params[1].get_array();
1844
0
        for (size_t i = 0; i < descs.size(); ++i) {
1845
0
            EvalDescriptorStringOrObject(descs[i], provider);
1846
0
        }
1847
0
    }
1848
1849
    // We don't actually need private keys further on; hide them as a precaution.
1850
0
    const PartiallySignedTransaction& psbtx = ProcessPSBT(
1851
0
        request.params[0].get_str(),
1852
0
        request.context,
1853
0
        HidingSigningProvider(&provider, /*hide_secret=*/true, /*hide_origin=*/false),
1854
0
        /*sighash_type=*/std::nullopt,
1855
0
        /*finalize=*/false);
1856
1857
0
    DataStream ssTx{};
1858
0
    ssTx << psbtx;
1859
0
    return EncodeBase64(ssTx);
1860
0
},
1861
0
    };
1862
0
}
1863
1864
static RPCMethod joinpsbts()
1865
0
{
1866
0
    return RPCMethod{
1867
0
        "joinpsbts",
1868
0
        "Joins multiple distinct version 0 PSBTs with different inputs and outputs into one version 0 PSBT with inputs and outputs from all of the PSBTs\n"
1869
0
            "No input in any of the PSBTs can be in more than one of the PSBTs.\n",
1870
0
            {
1871
0
                {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The base64 strings of partially signed transactions",
1872
0
                    {
1873
0
                        {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"}
1874
0
                    }}
1875
0
            },
1876
0
            RPCResult {
1877
0
                    RPCResult::Type::STR, "", "The base64-encoded partially signed transaction"
1878
0
            },
1879
0
            RPCExamples {
1880
0
                HelpExampleCli("joinpsbts", "\"psbt\"")
1881
0
            },
1882
0
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
1883
0
{
1884
    // Unserialize the transactions
1885
0
    std::vector<PartiallySignedTransaction> psbtxs;
1886
0
    UniValue txs = request.params[0].get_array();
1887
1888
0
    if (txs.size() <= 1) {
1889
0
        throw JSONRPCError(RPC_INVALID_PARAMETER, "At least two PSBTs are required to join PSBTs.");
1890
0
    }
1891
1892
0
    uint32_t best_version = 1;
1893
0
    uint32_t best_locktime = 0xffffffff;
1894
0
    for (unsigned int i = 0; i < txs.size(); ++i) {
1895
0
        util::Result<PartiallySignedTransaction> psbt_res = DecodeBase64PSBT(txs[i].get_str());
1896
0
        if (!psbt_res) {
1897
0
            throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", util::ErrorString(psbt_res).original));
Line
Count
Source
1172
0
#define strprintf tfm::format
1898
0
        }
1899
0
        psbtxs.push_back(*psbt_res);
1900
0
        const PartiallySignedTransaction& psbtx = psbtxs.back();
1901
0
        if (psbtx.GetVersion() != 0) {
1902
0
            throw JSONRPCError(RPC_INVALID_PARAMETER, "joinpsbts only operates on version 0 PSBTs");
1903
0
        }
1904
        // Choose the highest version number
1905
0
        if (psbtx.tx_version > best_version) {
1906
0
            best_version = psbtx.tx_version;
1907
0
        }
1908
        // Choose the lowest lock time
1909
0
        uint32_t psbt_locktime = psbtx.fallback_locktime.value_or(0);
1910
0
        if (psbt_locktime < best_locktime) {
1911
0
            best_locktime = psbt_locktime;
1912
0
        }
1913
0
    }
1914
1915
    // Create a blank psbt where everything will be added
1916
0
    CMutableTransaction tx;
1917
0
    tx.version = best_version;
1918
0
    tx.nLockTime = best_locktime;
1919
0
    PartiallySignedTransaction merged_psbt(tx, psbtxs.at(0).GetVersion());
1920
1921
    // Merge
1922
0
    for (auto& psbt : psbtxs) {
1923
0
        for (const PSBTInput& input : psbt.inputs) {
1924
0
            if (!merged_psbt.AddInput(input)) {
1925
0
                throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input %s:%d exists in multiple PSBTs", input.prev_txid.ToString(), input.prev_out));
Line
Count
Source
1172
0
#define strprintf tfm::format
1926
0
            }
1927
0
        }
1928
0
        for (const PSBTOutput& output : psbt.outputs) {
1929
0
            merged_psbt.AddOutput(output);
1930
0
        }
1931
0
        for (auto& xpub_pair : psbt.m_xpubs) {
1932
0
            if (!merged_psbt.m_xpubs.contains(xpub_pair.first)) {
1933
0
                merged_psbt.m_xpubs[xpub_pair.first] = xpub_pair.second;
1934
0
            } else {
1935
0
                merged_psbt.m_xpubs[xpub_pair.first].insert(xpub_pair.second.begin(), xpub_pair.second.end());
1936
0
            }
1937
0
        }
1938
0
        merged_psbt.unknown.insert(psbt.unknown.begin(), psbt.unknown.end());
1939
0
    }
1940
1941
    // Generate list of shuffled indices for shuffling inputs and outputs of the merged PSBT
1942
0
    std::vector<int> input_indices(merged_psbt.inputs.size());
1943
0
    std::iota(input_indices.begin(), input_indices.end(), 0);
1944
0
    std::vector<int> output_indices(merged_psbt.outputs.size());
1945
0
    std::iota(output_indices.begin(), output_indices.end(), 0);
1946
1947
    // Shuffle input and output indices lists
1948
0
    std::shuffle(input_indices.begin(), input_indices.end(), FastRandomContext());
1949
0
    std::shuffle(output_indices.begin(), output_indices.end(), FastRandomContext());
1950
1951
0
    PartiallySignedTransaction shuffled_psbt(tx, merged_psbt.GetVersion());
1952
0
    for (int i : input_indices) {
1953
0
        shuffled_psbt.AddInput(merged_psbt.inputs[i]);
1954
0
    }
1955
0
    for (int i : output_indices) {
1956
0
        shuffled_psbt.AddOutput(merged_psbt.outputs[i]);
1957
0
    }
1958
0
    shuffled_psbt.unknown.insert(merged_psbt.unknown.begin(), merged_psbt.unknown.end());
1959
1960
0
    DataStream ssTx{};
1961
0
    ssTx << shuffled_psbt;
1962
0
    return EncodeBase64(ssTx);
1963
0
},
1964
0
    };
1965
0
}
1966
1967
static RPCMethod analyzepsbt()
1968
0
{
1969
0
    return RPCMethod{
1970
0
        "analyzepsbt",
1971
0
        "Analyzes and provides information about the current status of a PSBT and its inputs\n",
1972
0
            {
1973
0
                {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"}
1974
0
            },
1975
0
            RPCResult {
1976
0
                RPCResult::Type::OBJ, "", "",
1977
0
                {
1978
0
                    {RPCResult::Type::ARR, "inputs", /*optional=*/true, "",
1979
0
                    {
1980
0
                        {RPCResult::Type::OBJ, "", "",
1981
0
                        {
1982
0
                            {RPCResult::Type::BOOL, "has_utxo", "Whether a UTXO is provided"},
1983
0
                            {RPCResult::Type::BOOL, "is_final", "Whether the input is finalized"},
1984
0
                            {RPCResult::Type::OBJ, "missing", /*optional=*/true, "Things that are missing that are required to complete this input",
1985
0
                            {
1986
0
                                {RPCResult::Type::ARR, "pubkeys", /*optional=*/true, "",
1987
0
                                {
1988
0
                                    {RPCResult::Type::STR_HEX, "keyid", "Public key ID, hash160 of the public key, of a public key whose BIP 32 derivation path is missing"},
1989
0
                                }},
1990
0
                                {RPCResult::Type::ARR, "signatures", /*optional=*/true, "",
1991
0
                                {
1992
0
                                    {RPCResult::Type::STR_HEX, "keyid", "Public key ID, hash160 of the public key, of a public key whose signature is missing"},
1993
0
                                }},
1994
0
                                {RPCResult::Type::STR_HEX, "redeemscript", /*optional=*/true, "Hash160 of the redeem script that is missing"},
1995
0
                                {RPCResult::Type::STR_HEX, "witnessscript", /*optional=*/true, "SHA256 of the witness script that is missing"},
1996
0
                            }},
1997
0
                            {RPCResult::Type::STR, "next", /*optional=*/true, "Role of the next person that this input needs to go to"},
1998
0
                        }},
1999
0
                    }},
2000
0
                    {RPCResult::Type::NUM, "estimated_vsize", /*optional=*/true, "Estimated vsize of the final signed transaction"},
2001
0
                    {RPCResult::Type::STR_AMOUNT, "estimated_feerate", /*optional=*/true, "Estimated feerate of the final signed transaction in " + CURRENCY_UNIT + "/kvB. Shown only if all UTXO slots in the PSBT have been filled"},
2002
0
                    {RPCResult::Type::STR_AMOUNT, "fee", /*optional=*/true, "The transaction fee paid. Shown only if all UTXO slots in the PSBT have been filled"},
2003
0
                    {RPCResult::Type::STR, "next", "Role of the next person that this psbt needs to go to"},
2004
0
                    {RPCResult::Type::STR, "error", /*optional=*/true, "Error message (if there is one)"},
2005
0
                }
2006
0
            },
2007
0
            RPCExamples {
2008
0
                HelpExampleCli("analyzepsbt", "\"psbt\"")
2009
0
            },
2010
0
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
2011
0
{
2012
    // Unserialize the transaction
2013
0
    util::Result<PartiallySignedTransaction> psbt_res = DecodeBase64PSBT(request.params[0].get_str());
2014
0
    if (!psbt_res) {
2015
0
        throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", util::ErrorString(psbt_res).original));
Line
Count
Source
1172
0
#define strprintf tfm::format
2016
0
    }
2017
0
    const PartiallySignedTransaction& psbtx = *psbt_res;
2018
2019
0
    PSBTAnalysis psbta = AnalyzePSBT(psbtx);
2020
2021
0
    UniValue result(UniValue::VOBJ);
2022
0
    UniValue inputs_result(UniValue::VARR);
2023
0
    for (const auto& input : psbta.inputs) {
2024
0
        UniValue input_univ(UniValue::VOBJ);
2025
0
        UniValue missing(UniValue::VOBJ);
2026
2027
0
        input_univ.pushKV("has_utxo", input.has_utxo);
2028
0
        input_univ.pushKV("is_final", input.is_final);
2029
0
        input_univ.pushKV("next", PSBTRoleName(input.next));
2030
2031
0
        if (!input.missing_pubkeys.empty()) {
2032
0
            UniValue missing_pubkeys_univ(UniValue::VARR);
2033
0
            for (const CKeyID& pubkey : input.missing_pubkeys) {
2034
0
                missing_pubkeys_univ.push_back(HexStr(pubkey));
2035
0
            }
2036
0
            missing.pushKV("pubkeys", std::move(missing_pubkeys_univ));
2037
0
        }
2038
0
        if (!input.missing_redeem_script.IsNull()) {
2039
0
            missing.pushKV("redeemscript", HexStr(input.missing_redeem_script));
2040
0
        }
2041
0
        if (!input.missing_witness_script.IsNull()) {
2042
0
            missing.pushKV("witnessscript", HexStr(input.missing_witness_script));
2043
0
        }
2044
0
        if (!input.missing_sigs.empty()) {
2045
0
            UniValue missing_sigs_univ(UniValue::VARR);
2046
0
            for (const CKeyID& pubkey : input.missing_sigs) {
2047
0
                missing_sigs_univ.push_back(HexStr(pubkey));
2048
0
            }
2049
0
            missing.pushKV("signatures", std::move(missing_sigs_univ));
2050
0
        }
2051
0
        if (!missing.getKeys().empty()) {
2052
0
            input_univ.pushKV("missing", std::move(missing));
2053
0
        }
2054
0
        inputs_result.push_back(std::move(input_univ));
2055
0
    }
2056
0
    if (!inputs_result.empty()) result.pushKV("inputs", std::move(inputs_result));
2057
2058
0
    if (psbta.estimated_vsize != std::nullopt) {
2059
0
        result.pushKV("estimated_vsize", *psbta.estimated_vsize);
2060
0
    }
2061
0
    if (psbta.estimated_feerate != std::nullopt) {
2062
0
        result.pushKV("estimated_feerate", ValueFromAmount(psbta.estimated_feerate->GetFeePerK()));
2063
0
    }
2064
0
    if (psbta.fee != std::nullopt) {
2065
0
        result.pushKV("fee", ValueFromAmount(*psbta.fee));
2066
0
    }
2067
0
    result.pushKV("next", PSBTRoleName(psbta.next));
2068
0
    if (!psbta.error.empty()) {
2069
0
        result.pushKV("error", psbta.error);
2070
0
    }
2071
2072
0
    return result;
2073
0
},
2074
0
    };
2075
0
}
2076
2077
RPCMethod descriptorprocesspsbt()
2078
0
{
2079
0
    return RPCMethod{
2080
0
        "descriptorprocesspsbt",
2081
0
        "Update all segwit inputs in a PSBT with information from output descriptors, the UTXO set or the mempool. \n"
2082
0
                "Then, sign the inputs we are able to with information from the output descriptors. ",
2083
0
                {
2084
0
                    {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction base64 string"},
2085
0
                    {"descriptors", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of either strings or objects", {
2086
0
                        {"", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "An output descriptor"},
2087
0
                        {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "An object with an output descriptor and extra information", {
2088
0
                             {"desc", RPCArg::Type::STR, RPCArg::Optional::NO, "An output descriptor"},
2089
0
                             {"range", RPCArg::Type::RANGE, RPCArg::Default{1000}, "Up to what index HD chains should be explored (either end or [begin,end])"},
2090
0
                        }},
2091
0
                    }},
2092
0
                    {"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"
2093
0
            "       \"DEFAULT\"\n"
2094
0
            "       \"ALL\"\n"
2095
0
            "       \"NONE\"\n"
2096
0
            "       \"SINGLE\"\n"
2097
0
            "       \"ALL|ANYONECANPAY\"\n"
2098
0
            "       \"NONE|ANYONECANPAY\"\n"
2099
0
            "       \"SINGLE|ANYONECANPAY\""},
2100
0
                    {"bip32derivs", RPCArg::Type::BOOL, RPCArg::Default{true}, "Include BIP 32 derivation paths for public keys if we know them"},
2101
0
                    {"finalize", RPCArg::Type::BOOL, RPCArg::Default{true}, "Also finalize inputs if possible"},
2102
0
                },
2103
0
                RPCResult{
2104
0
                    RPCResult::Type::OBJ, "", "",
2105
0
                    {
2106
0
                        {RPCResult::Type::STR, "psbt", "The base64-encoded partially signed transaction"},
2107
0
                        {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
2108
0
                        {RPCResult::Type::STR_HEX, "hex", /*optional=*/true, "The hex-encoded network transaction if complete"},
2109
0
                    }
2110
0
                },
2111
0
                RPCExamples{
2112
0
                    HelpExampleCli("descriptorprocesspsbt", "\"psbt\" \"[\\\"descriptor1\\\", \\\"descriptor2\\\"]\"") +
2113
0
                    HelpExampleCli("descriptorprocesspsbt", "\"psbt\" \"[{\\\"desc\\\":\\\"mydescriptor\\\", \\\"range\\\":21}]\"")
2114
0
                },
2115
0
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
2116
0
{
2117
    // Add descriptor information to a signing provider
2118
0
    FlatSigningProvider provider;
2119
2120
0
    auto descs = request.params[1].get_array();
2121
0
    for (size_t i = 0; i < descs.size(); ++i) {
2122
0
        EvalDescriptorStringOrObject(descs[i], provider, /*expand_priv=*/true);
2123
0
    }
2124
2125
0
    std::optional<int> sighash_type = ParseSighashString(request.params[2]);
2126
0
    bool bip32derivs = request.params[3].isNull() ? true : request.params[3].get_bool();
2127
0
    bool finalize = request.params[4].isNull() ? true : request.params[4].get_bool();
2128
2129
0
    const PartiallySignedTransaction& psbtx = ProcessPSBT(
2130
0
        request.params[0].get_str(),
2131
0
        request.context,
2132
0
        HidingSigningProvider(&provider, /*hide_secret=*/false, !bip32derivs),
2133
0
        sighash_type,
2134
0
        finalize);
2135
2136
    // Check whether or not all of the inputs are now correctly signed
2137
0
    bool complete = true;
2138
0
    const std::optional<PrecomputedTransactionData> txdata_opt{PrecomputePSBTData(psbtx)};
2139
0
    const PrecomputedTransactionData txdata{*CHECK_NONFATAL(txdata_opt)};
Line
Count
Source
113
0
    inline_check_non_fatal(condition, std::source_location::current(), #condition)
2140
0
    for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {
2141
0
        complete = complete && PSBTInputSignedAndVerified(psbtx, i, &txdata);
2142
0
    }
2143
2144
0
    DataStream ssTx{};
2145
0
    ssTx << psbtx;
2146
2147
0
    UniValue result(UniValue::VOBJ);
2148
2149
0
    result.pushKV("psbt", EncodeBase64(ssTx));
2150
0
    result.pushKV("complete", complete);
2151
0
    if (complete) {
2152
0
        CMutableTransaction mtx;
2153
0
        PartiallySignedTransaction psbtx_copy = psbtx;
2154
0
        CHECK_NONFATAL(FinalizeAndExtractPSBT(psbtx_copy, mtx));
Line
Count
Source
113
0
    inline_check_non_fatal(condition, std::source_location::current(), #condition)
2155
0
        DataStream ssTx_final;
2156
0
        ssTx_final << TX_WITH_WITNESS(mtx);
2157
0
        result.pushKV("hex", HexStr(ssTx_final));
2158
0
    }
2159
0
    return result;
2160
0
},
2161
0
    };
2162
0
}
2163
2164
void RegisterRawTransactionRPCCommands(CRPCTable& t)
2165
0
{
2166
0
    static const CRPCCommand commands[]{
2167
0
        {"rawtransactions", &getrawtransaction},
2168
0
        {"rawtransactions", &createrawtransaction},
2169
0
        {"rawtransactions", &decoderawtransaction},
2170
0
        {"rawtransactions", &decodescript},
2171
0
        {"rawtransactions", &combinerawtransaction},
2172
0
        {"rawtransactions", &signrawtransactionwithkey},
2173
0
        {"rawtransactions", &decodepsbt},
2174
0
        {"rawtransactions", &combinepsbt},
2175
0
        {"rawtransactions", &finalizepsbt},
2176
0
        {"rawtransactions", &createpsbt},
2177
0
        {"rawtransactions", &converttopsbt},
2178
0
        {"rawtransactions", &utxoupdatepsbt},
2179
0
        {"rawtransactions", &descriptorprocesspsbt},
2180
0
        {"rawtransactions", &joinpsbts},
2181
0
        {"rawtransactions", &analyzepsbt},
2182
0
    };
2183
0
    for (const auto& c : commands) {
2184
0
        t.appendCommand(c.name, &c);
2185
0
    }
2186
0
}