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