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