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