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