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