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