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