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