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