Line data Source code
1 : // Copyright (c) 2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2020 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 <chain.h>
7 : #include <coins.h>
8 : #include <consensus/validation.h>
9 : #include <core_io.h>
10 : #include <index/txindex.h>
11 : #include <key_io.h>
12 : #include <merkleblock.h>
13 : #include <node/coin.h>
14 : #include <node/context.h>
15 : #include <node/psbt.h>
16 : #include <node/transaction.h>
17 : #include <policy/policy.h>
18 : #include <policy/rbf.h>
19 : #include <primitives/transaction.h>
20 : #include <psbt.h>
21 : #include <random.h>
22 : #include <rpc/blockchain.h>
23 : #include <rpc/rawtransaction_util.h>
24 : #include <rpc/server.h>
25 : #include <rpc/util.h>
26 : #include <script/script.h>
27 : #include <script/sign.h>
28 : #include <script/signingprovider.h>
29 : #include <script/standard.h>
30 : #include <uint256.h>
31 : #include <util/bip32.h>
32 : #include <util/moneystr.h>
33 : #include <util/strencodings.h>
34 : #include <util/string.h>
35 : #include <validation.h>
36 : #include <validationinterface.h>
37 :
38 :
39 : #include <numeric>
40 : #include <stdint.h>
41 :
42 : #include <univalue.h>
43 :
44 283 : static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
45 : {
46 : // Call into TxToUniv() in bitcoin-common to decode the transaction hex.
47 : //
48 : // Blockchain contextual information (confirmations and blocktime) is not
49 : // available to code in bitcoin-common, so we query them here and push the
50 : // data into the returned UniValue.
51 283 : TxToUniv(tx, uint256(), entry, true, RPCSerializationFlags());
52 :
53 283 : if (!hashBlock.IsNull()) {
54 35 : LOCK(cs_main);
55 :
56 35 : entry.pushKV("blockhash", hashBlock.GetHex());
57 35 : CBlockIndex* pindex = LookupBlockIndex(hashBlock);
58 35 : if (pindex) {
59 35 : if (::ChainActive().Contains(pindex)) {
60 34 : entry.pushKV("confirmations", 1 + ::ChainActive().Height() - pindex->nHeight);
61 34 : entry.pushKV("time", pindex->GetBlockTime());
62 34 : entry.pushKV("blocktime", pindex->GetBlockTime());
63 34 : }
64 : else
65 1 : entry.pushKV("confirmations", 0);
66 : }
67 35 : }
68 283 : }
69 :
70 683 : static UniValue getrawtransaction(const JSONRPCRequest& request)
71 : {
72 21181 : RPCHelpMan{
73 683 : "getrawtransaction",
74 683 : "\nReturn the raw transaction data.\n"
75 :
76 : "\nBy default this function only works for mempool transactions. When called with a blockhash\n"
77 : "argument, getrawtransaction will return the transaction if the specified block is available and\n"
78 : "the transaction is found in that block. When called without a blockhash argument, getrawtransaction\n"
79 : "will return the transaction if it is in the mempool, or if -txindex is enabled and the transaction\n"
80 : "is in a block in the blockchain.\n"
81 :
82 : "\nHint: Use gettransaction for wallet transactions.\n"
83 :
84 : "\nIf verbose is 'true', returns an Object with information about 'txid'.\n"
85 : "If verbose is 'false' or omitted, returns a string that is serialized, hex-encoded data for 'txid'.\n",
86 2737 : {
87 683 : {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
88 683 : {"verbose", RPCArg::Type::BOOL, /* default */ "false", "If false, return a string, otherwise return a json object"},
89 683 : {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED_NAMED_ARG, "The block in which to look for the transaction"},
90 : },
91 2054 : {
92 1366 : RPCResult{"if verbose is not set or set to false",
93 683 : RPCResult::Type::STR, "data", "The serialized, hex-encoded data for 'txid'"
94 : },
95 1366 : RPCResult{"if verbose is set to true",
96 683 : RPCResult::Type::OBJ, "", "",
97 11013 : {
98 683 : {RPCResult::Type::BOOL, "in_active_chain", "Whether specified block is in the active chain or not (only present with explicit \"blockhash\" argument)"},
99 683 : {RPCResult::Type::STR_HEX, "hex", "The serialized, hex-encoded data for 'txid'"},
100 683 : {RPCResult::Type::STR_HEX, "txid", "The transaction id (same as provided)"},
101 683 : {RPCResult::Type::STR_HEX, "hash", "The transaction hash (differs from txid for witness transactions)"},
102 683 : {RPCResult::Type::NUM, "size", "The serialized transaction size"},
103 683 : {RPCResult::Type::NUM, "vsize", "The virtual transaction size (differs from size for witness transactions)"},
104 683 : {RPCResult::Type::NUM, "weight", "The transaction's weight (between vsize*4-3 and vsize*4)"},
105 683 : {RPCResult::Type::NUM, "version", "The version"},
106 683 : {RPCResult::Type::NUM_TIME, "locktime", "The lock time"},
107 1366 : {RPCResult::Type::ARR, "vin", "",
108 1366 : {
109 1366 : {RPCResult::Type::OBJ, "", "",
110 4113 : {
111 683 : {RPCResult::Type::STR_HEX, "txid", "The transaction id"},
112 683 : {RPCResult::Type::STR, "vout", ""},
113 1366 : {RPCResult::Type::OBJ, "scriptSig", "The script",
114 2054 : {
115 683 : {RPCResult::Type::STR, "asm", "asm"},
116 683 : {RPCResult::Type::STR_HEX, "hex", "hex"},
117 : }},
118 683 : {RPCResult::Type::NUM, "sequence", "The script sequence number"},
119 1366 : {RPCResult::Type::ARR, "txinwitness", "",
120 1366 : {
121 683 : {RPCResult::Type::STR_HEX, "hex", "hex-encoded witness data (if any)"},
122 : }},
123 : }},
124 : }},
125 1366 : {RPCResult::Type::ARR, "vout", "",
126 1366 : {
127 1366 : {RPCResult::Type::OBJ, "", "",
128 2737 : {
129 683 : {RPCResult::Type::NUM, "value", "The value in " + CURRENCY_UNIT},
130 683 : {RPCResult::Type::NUM, "n", "index"},
131 1366 : {RPCResult::Type::OBJ, "scriptPubKey", "",
132 4103 : {
133 683 : {RPCResult::Type::STR, "asm", "the asm"},
134 683 : {RPCResult::Type::STR, "hex", "the hex"},
135 683 : {RPCResult::Type::NUM, "reqSigs", "The required sigs"},
136 683 : {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
137 1366 : {RPCResult::Type::ARR, "addresses", "",
138 1366 : {
139 683 : {RPCResult::Type::STR, "address", "bitcoin address"},
140 : }},
141 : }},
142 : }},
143 : }},
144 683 : {RPCResult::Type::STR_HEX, "blockhash", "the block hash"},
145 683 : {RPCResult::Type::NUM, "confirmations", "The confirmations"},
146 683 : {RPCResult::Type::NUM_TIME, "blocktime", "The block time expressed in " + UNIX_EPOCH_TIME},
147 683 : {RPCResult::Type::NUM, "time", "Same as \"blocktime\""},
148 : }
149 : },
150 : },
151 683 : RPCExamples{
152 683 : HelpExampleCli("getrawtransaction", "\"mytxid\"")
153 683 : + HelpExampleCli("getrawtransaction", "\"mytxid\" true")
154 683 : + HelpExampleRpc("getrawtransaction", "\"mytxid\", true")
155 683 : + HelpExampleCli("getrawtransaction", "\"mytxid\" false \"myblockhash\"")
156 683 : + HelpExampleCli("getrawtransaction", "\"mytxid\" true \"myblockhash\"")
157 : },
158 683 : }.Check(request);
159 :
160 678 : const NodeContext& node = EnsureNodeContext(request.context);
161 :
162 : bool in_active_chain = true;
163 678 : uint256 hash = ParseHashV(request.params[0], "parameter 1");
164 : CBlockIndex* blockindex = nullptr;
165 :
166 677 : if (hash == Params().GenesisBlock().hashMerkleRoot) {
167 : // Special exception for the genesis block coinbase transaction
168 1 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "The genesis block coinbase is not considered an ordinary transaction and cannot be retrieved");
169 : }
170 :
171 : // Accept either a bool (true) or a num (>=1) to indicate verbose output.
172 : bool fVerbose = false;
173 676 : if (!request.params[1].isNull()) {
174 335 : fVerbose = request.params[1].isNum() ? (request.params[1].get_int() != 0) : request.params[1].get_bool();
175 332 : }
176 :
177 673 : if (!request.params[2].isNull()) {
178 79 : LOCK(cs_main);
179 :
180 79 : uint256 blockhash = ParseHashV(request.params[2], "parameter 3");
181 75 : blockindex = LookupBlockIndex(blockhash);
182 75 : if (!blockindex) {
183 1 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block hash not found");
184 : }
185 74 : in_active_chain = ::ChainActive().Contains(blockindex);
186 79 : }
187 :
188 : bool f_txindex_ready = false;
189 668 : if (g_txindex && !blockindex) {
190 9 : f_txindex_ready = g_txindex->BlockUntilSyncedToCurrentChain();
191 9 : }
192 :
193 668 : uint256 hash_block;
194 668 : const CTransactionRef tx = GetTransaction(blockindex, node.mempool.get(), hash, Params().GetConsensus(), hash_block);
195 668 : if (!tx) {
196 1 : std::string errmsg;
197 1 : if (blockindex) {
198 1 : if (!(blockindex->nStatus & BLOCK_HAVE_DATA)) {
199 0 : throw JSONRPCError(RPC_MISC_ERROR, "Block not available");
200 : }
201 1 : errmsg = "No such transaction found in the provided block";
202 0 : } else if (!g_txindex) {
203 0 : errmsg = "No such mempool transaction. Use -txindex or provide a block hash to enable blockchain transaction queries";
204 0 : } else if (!f_txindex_ready) {
205 0 : errmsg = "No such mempool transaction. Blockchain transactions are still in the process of being indexed";
206 : } else {
207 0 : errmsg = "No such mempool or blockchain transaction";
208 : }
209 1 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, errmsg + ". Use gettransaction for wallet transactions.");
210 1 : }
211 :
212 667 : if (!fVerbose) {
213 384 : return EncodeHexTx(*tx, RPCSerializationFlags());
214 : }
215 :
216 283 : UniValue result(UniValue::VOBJ);
217 283 : if (blockindex) result.pushKV("in_active_chain", in_active_chain);
218 283 : TxToJSON(*tx, hash_block, result);
219 283 : return result;
220 811 : }
221 :
222 26 : static UniValue gettxoutproof(const JSONRPCRequest& request)
223 : {
224 114 : RPCHelpMan{"gettxoutproof",
225 26 : "\nReturns a hex-encoded proof that \"txid\" was included in a block.\n"
226 : "\nNOTE: By default this function only works sometimes. This is when there is an\n"
227 : "unspent output in the utxo for this transaction. To make it always work,\n"
228 : "you need to maintain a transaction index, using the -txindex command line option or\n"
229 : "specify the block in which the transaction is included manually (by blockhash).\n",
230 90 : {
231 52 : {"txids", RPCArg::Type::ARR, RPCArg::Optional::NO, "The txids to filter",
232 52 : {
233 26 : {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A transaction hash"},
234 : },
235 : },
236 26 : {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED_NAMED_ARG, "If specified, looks for txid in the block with this hash"},
237 : },
238 26 : RPCResult{
239 26 : RPCResult::Type::STR, "data", "A string that is a serialized, hex-encoded data for the proof."
240 : },
241 26 : RPCExamples{""},
242 26 : }.Check(request);
243 :
244 22 : std::set<uint256> setTxids;
245 22 : uint256 oneTxid;
246 22 : UniValue txids = request.params[0].get_array();
247 50 : for (unsigned int idx = 0; idx < txids.size(); idx++) {
248 28 : const UniValue& txid = txids[idx];
249 28 : uint256 hash(ParseHashV(txid, "txid"));
250 26 : if (setTxids.count(hash)) {
251 1 : throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated txid: ") + txid.get_str());
252 : }
253 25 : setTxids.insert(hash);
254 25 : oneTxid = hash;
255 28 : }
256 :
257 31 : CBlockIndex* pblockindex = nullptr;
258 19 : uint256 hashBlock;
259 19 : if (!request.params[1].isNull()) {
260 5 : LOCK(cs_main);
261 5 : hashBlock = ParseHashV(request.params[1], "blockhash");
262 3 : pblockindex = LookupBlockIndex(hashBlock);
263 3 : if (!pblockindex) {
264 1 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
265 : }
266 5 : } else {
267 14 : LOCK(cs_main);
268 :
269 : // Loop through txids and try to find which block they're in. Exit loop once a block is found.
270 27 : for (const auto& tx : setTxids) {
271 13 : const Coin& coin = AccessByTxid(::ChainstateActive().CoinsTip(), tx);
272 13 : if (!coin.IsSpent()) {
273 10 : pblockindex = ::ChainActive()[coin.nHeight];
274 10 : break;
275 : }
276 6 : }
277 14 : }
278 :
279 :
280 : // Allow txindex to catch up if we need to query it and before we acquire cs_main.
281 16 : if (g_txindex && !pblockindex) {
282 1 : g_txindex->BlockUntilSyncedToCurrentChain();
283 : }
284 :
285 16 : LOCK(cs_main);
286 :
287 16 : if (pblockindex == nullptr) {
288 4 : const CTransactionRef tx = GetTransaction(/* block_index */ nullptr, /* mempool */ nullptr, oneTxid, Params().GetConsensus(), hashBlock);
289 4 : if (!tx || hashBlock.IsNull()) {
290 3 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not yet in block");
291 : }
292 1 : pblockindex = LookupBlockIndex(hashBlock);
293 1 : if (!pblockindex) {
294 0 : throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction index corrupt");
295 : }
296 4 : }
297 :
298 13 : CBlock block;
299 13 : if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) {
300 0 : throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
301 : }
302 :
303 : unsigned int ntxFound = 0;
304 49 : for (const auto& tx : block.vtx) {
305 36 : if (setTxids.count(tx->GetHash())) {
306 18 : ntxFound++;
307 18 : }
308 : }
309 13 : if (ntxFound != setTxids.size()) {
310 1 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Not all transactions found in specified or retrieved block");
311 : }
312 :
313 12 : CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
314 12 : CMerkleBlock mb(block, setTxids);
315 12 : ssMB << mb;
316 12 : std::string strHex = HexStr(ssMB);
317 12 : return strHex;
318 63 : }
319 :
320 17 : static UniValue verifytxoutproof(const JSONRPCRequest& request)
321 : {
322 51 : RPCHelpMan{"verifytxoutproof",
323 17 : "\nVerifies that a proof points to a transaction in a block, returning the transaction it commits to\n"
324 : "and throwing an RPC error if the block is not in our best chain\n",
325 34 : {
326 17 : {"proof", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded proof generated by gettxoutproof"},
327 : },
328 17 : RPCResult{
329 17 : RPCResult::Type::ARR, "", "",
330 34 : {
331 17 : {RPCResult::Type::STR_HEX, "txid", "The txid(s) which the proof commits to, or empty array if the proof can not be validated."},
332 : }
333 : },
334 17 : RPCExamples{""},
335 17 : }.Check(request);
336 :
337 13 : CDataStream ssMB(ParseHexV(request.params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
338 13 : CMerkleBlock merkleBlock;
339 13 : ssMB >> merkleBlock;
340 :
341 13 : UniValue res(UniValue::VARR);
342 :
343 13 : std::vector<uint256> vMatch;
344 13 : std::vector<unsigned int> vIndex;
345 13 : if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) != merkleBlock.header.hashMerkleRoot)
346 0 : return res;
347 :
348 13 : LOCK(cs_main);
349 :
350 13 : const CBlockIndex* pindex = LookupBlockIndex(merkleBlock.header.GetHash());
351 13 : if (!pindex || !::ChainActive().Contains(pindex) || pindex->nTx == 0) {
352 0 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain");
353 : }
354 :
355 : // Check if proof is valid, only add results if so
356 13 : if (pindex->nTx == merkleBlock.txn.GetNumTransactions()) {
357 29 : for (const uint256& hash : vMatch) {
358 18 : res.push_back(hash.GetHex());
359 : }
360 11 : }
361 :
362 : return res;
363 37 : }
364 :
365 1067 : static UniValue createrawtransaction(const JSONRPCRequest& request)
366 : {
367 9607 : RPCHelpMan{"createrawtransaction",
368 1067 : "\nCreate a transaction spending the given inputs and creating new outputs.\n"
369 : "Outputs can be addresses or data.\n"
370 : "Returns hex-encoded raw transaction.\n"
371 : "Note that the transaction's inputs are not signed, and\n"
372 : "it is not stored in the wallet or transmitted to the network.\n",
373 5423 : {
374 2134 : {"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The inputs",
375 2134 : {
376 2134 : {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
377 4276 : {
378 1067 : {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
379 1067 : {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
380 1067 : {"sequence", RPCArg::Type::NUM, /* default */ "depends on the value of the 'replaceable' and 'locktime' arguments", "The sequence number"},
381 : },
382 : },
383 : },
384 : },
385 2134 : {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The outputs (key-value pairs), where none of the keys are duplicated.\n"
386 : "That is, each address can only appear once and there can only be one 'data' object.\n"
387 : "For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n"
388 : " accepted as second parameter.",
389 3225 : {
390 2134 : {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
391 2134 : {
392 1067 : {"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},
393 : },
394 : },
395 2134 : {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
396 2134 : {
397 1067 : {"data", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A key-value pair. The key must be \"data\", the value is hex-encoded data"},
398 : },
399 : },
400 : },
401 : },
402 1067 : {"locktime", RPCArg::Type::NUM, /* default */ "0", "Raw locktime. Non-0 value also locktime-activates inputs"},
403 1067 : {"replaceable", RPCArg::Type::BOOL, /* default */ "false", "Marks this transaction as BIP125-replaceable.\n"
404 : " Allows this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible."},
405 : },
406 1067 : RPCResult{
407 1067 : RPCResult::Type::STR_HEX, "transaction", "hex string of the transaction"
408 : },
409 1067 : RPCExamples{
410 1067 : HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"address\\\":0.01}]\"")
411 1067 : + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"")
412 1067 : + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"[{\\\"address\\\":0.01}]\"")
413 1067 : + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"[{\\\"data\\\":\\\"00010203\\\"}]\"")
414 : },
415 1067 : }.Check(request);
416 :
417 5295 : RPCTypeCheck(request.params, {
418 1059 : UniValue::VARR,
419 1059 : UniValueType(), // ARR or OBJ, checked later
420 1059 : UniValue::VNUM,
421 1059 : UniValue::VBOOL
422 : }, true
423 : );
424 :
425 : bool rbf = false;
426 1055 : if (!request.params[3].isNull()) {
427 40 : rbf = request.params[3].isTrue();
428 40 : }
429 1055 : CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], rbf);
430 :
431 1055 : return EncodeHexTx(CTransaction(rawTx));
432 1232 : }
433 :
434 138 : static UniValue decoderawtransaction(const JSONRPCRequest& request)
435 : {
436 3180 : RPCHelpMan{"decoderawtransaction",
437 138 : "\nReturn a JSON object representing the serialized, hex-encoded transaction.\n",
438 420 : {
439 138 : {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction hex string"},
440 138 : {"iswitness", RPCArg::Type::BOOL, /* default */ "depends on heuristic tests", "Whether the transaction hex is a serialized witness transaction.\n"
441 : "If iswitness is not present, heuristic tests will be used in decoding.\n"
442 : "If true, only witness deserialization will be tried.\n"
443 : "If false, only non-witness deserialization will be tried.\n"
444 : "This boolean should reflect whether the transaction has inputs\n"
445 : "(e.g. fully valid, or on-chain transactions), if known by the caller."
446 : },
447 : },
448 138 : RPCResult{
449 138 : RPCResult::Type::OBJ, "", "",
450 1434 : {
451 138 : {RPCResult::Type::STR_HEX, "txid", "The transaction id"},
452 138 : {RPCResult::Type::STR_HEX, "hash", "The transaction hash (differs from txid for witness transactions)"},
453 138 : {RPCResult::Type::NUM, "size", "The transaction size"},
454 138 : {RPCResult::Type::NUM, "vsize", "The virtual transaction size (differs from size for witness transactions)"},
455 138 : {RPCResult::Type::NUM, "weight", "The transaction's weight (between vsize*4 - 3 and vsize*4)"},
456 138 : {RPCResult::Type::NUM, "version", "The version"},
457 138 : {RPCResult::Type::NUM_TIME, "locktime", "The lock time"},
458 276 : {RPCResult::Type::ARR, "vin", "",
459 276 : {
460 276 : {RPCResult::Type::OBJ, "", "",
461 858 : {
462 138 : {RPCResult::Type::STR_HEX, "txid", "The transaction id"},
463 138 : {RPCResult::Type::NUM, "vout", "The output number"},
464 276 : {RPCResult::Type::OBJ, "scriptSig", "The script",
465 420 : {
466 138 : {RPCResult::Type::STR, "asm", "asm"},
467 138 : {RPCResult::Type::STR_HEX, "hex", "hex"},
468 : }},
469 276 : {RPCResult::Type::ARR, "txinwitness", "",
470 276 : {
471 138 : {RPCResult::Type::STR_HEX, "hex", "hex-encoded witness data (if any)"},
472 : }},
473 138 : {RPCResult::Type::NUM, "sequence", "The script sequence number"},
474 : }},
475 : }},
476 276 : {RPCResult::Type::ARR, "vout", "",
477 276 : {
478 276 : {RPCResult::Type::OBJ, "", "",
479 558 : {
480 138 : {RPCResult::Type::NUM, "value", "The value in " + CURRENCY_UNIT},
481 138 : {RPCResult::Type::NUM, "n", "index"},
482 276 : {RPCResult::Type::OBJ, "scriptPubKey", "",
483 834 : {
484 138 : {RPCResult::Type::STR, "asm", "the asm"},
485 138 : {RPCResult::Type::STR_HEX, "hex", "the hex"},
486 138 : {RPCResult::Type::NUM, "reqSigs", "The required sigs"},
487 138 : {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
488 276 : {RPCResult::Type::ARR, "addresses", "",
489 276 : {
490 138 : {RPCResult::Type::STR, "address", "bitcoin address"},
491 : }},
492 : }},
493 : }},
494 : }},
495 : }
496 : },
497 138 : RPCExamples{
498 138 : HelpExampleCli("decoderawtransaction", "\"hexstring\"")
499 138 : + HelpExampleRpc("decoderawtransaction", "\"hexstring\"")
500 : },
501 138 : }.Check(request);
502 :
503 132 : RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL});
504 :
505 132 : CMutableTransaction mtx;
506 :
507 132 : bool try_witness = request.params[1].isNull() ? true : request.params[1].get_bool();
508 132 : bool try_no_witness = request.params[1].isNull() ? true : !request.params[1].get_bool();
509 :
510 132 : if (!DecodeHexTx(mtx, request.params[0].get_str(), try_no_witness, try_witness)) {
511 6 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
512 : }
513 :
514 126 : UniValue result(UniValue::VOBJ);
515 126 : TxToUniv(CTransaction(std::move(mtx)), uint256(), result, false);
516 :
517 : return result;
518 270 : }
519 :
520 25 : static std::string GetAllOutputTypes()
521 : {
522 25 : std::vector<std::string> ret;
523 : using U = std::underlying_type<TxoutType>::type;
524 250 : for (U i = (U)TxoutType::NONSTANDARD; i <= (U)TxoutType::WITNESS_UNKNOWN; ++i) {
525 225 : ret.emplace_back(GetTxnOutputType(static_cast<TxoutType>(i)));
526 : }
527 25 : return Join(ret, ", ");
528 25 : }
529 :
530 25 : static UniValue decodescript(const JSONRPCRequest& request)
531 : {
532 325 : RPCHelpMan{"decodescript",
533 25 : "\nDecode a hex-encoded script.\n",
534 50 : {
535 25 : {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded script"},
536 : },
537 25 : RPCResult{
538 25 : RPCResult::Type::OBJ, "", "",
539 187 : {
540 25 : {RPCResult::Type::STR, "asm", "Script public key"},
541 25 : {RPCResult::Type::STR, "type", "The output type (e.g. "+GetAllOutputTypes()+")"},
542 25 : {RPCResult::Type::NUM, "reqSigs", "The required signatures"},
543 50 : {RPCResult::Type::ARR, "addresses", "",
544 50 : {
545 25 : {RPCResult::Type::STR, "address", "bitcoin address"},
546 : }},
547 25 : {RPCResult::Type::STR, "p2sh", "address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH)"},
548 50 : {RPCResult::Type::OBJ, "segwit", "Result of a witness script public key wrapping this redeem script (not returned if the script is a P2SH or witness)",
549 187 : {
550 25 : {RPCResult::Type::STR, "asm", "String representation of the script public key"},
551 25 : {RPCResult::Type::STR_HEX, "hex", "Hex string of the script public key"},
552 25 : {RPCResult::Type::STR, "type", "The type of the script public key (e.g. witness_v0_keyhash or witness_v0_scripthash)"},
553 25 : {RPCResult::Type::NUM, "reqSigs", "The required signatures (always 1)"},
554 50 : {RPCResult::Type::ARR, "addresses", "(always length 1)",
555 50 : {
556 25 : {RPCResult::Type::STR, "address", "segwit address"},
557 : }},
558 25 : {RPCResult::Type::STR, "p2sh-segwit", "address of the P2SH script wrapping this witness redeem script"},
559 : }},
560 : }
561 : },
562 25 : RPCExamples{
563 25 : HelpExampleCli("decodescript", "\"hexstring\"")
564 25 : + HelpExampleRpc("decodescript", "\"hexstring\"")
565 : },
566 25 : }.Check(request);
567 :
568 21 : RPCTypeCheck(request.params, {UniValue::VSTR});
569 :
570 21 : UniValue r(UniValue::VOBJ);
571 21 : CScript script;
572 21 : if (request.params[0].get_str().size() > 0){
573 21 : std::vector<unsigned char> scriptData(ParseHexV(request.params[0], "argument"));
574 21 : script = CScript(scriptData.begin(), scriptData.end());
575 21 : } else {
576 : // Empty scripts are valid
577 : }
578 21 : ScriptPubKeyToUniv(script, r, /* fIncludeHex */ false);
579 :
580 21 : UniValue type;
581 21 : type = find_value(r, "type");
582 :
583 21 : if (type.isStr() && type.get_str() != "scripthash") {
584 : // P2SH cannot be wrapped in a P2SH. If this script is already a P2SH,
585 : // don't return the address for a P2SH of the P2SH.
586 16 : r.pushKV("p2sh", EncodeDestination(ScriptHash(script)));
587 : // P2SH and witness programs cannot be wrapped in P2WSH, if this script
588 : // is a witness program, don't return addresses for a segwit programs.
589 16 : if (type.get_str() == "pubkey" || type.get_str() == "pubkeyhash" || type.get_str() == "multisig" || type.get_str() == "nonstandard") {
590 13 : std::vector<std::vector<unsigned char>> solutions_data;
591 13 : TxoutType which_type = Solver(script, solutions_data);
592 : // Uncompressed pubkeys cannot be used with segwit checksigs.
593 : // If the script contains an uncompressed pubkey, skip encoding of a segwit program.
594 13 : if ((which_type == TxoutType::PUBKEY) || (which_type == TxoutType::MULTISIG)) {
595 14 : for (const auto& solution : solutions_data) {
596 10 : if ((solution.size() != 1) && !CPubKey(solution).IsCompressed()) {
597 15 : return r;
598 : }
599 8 : }
600 : }
601 11 : UniValue sr(UniValue::VOBJ);
602 11 : CScript segwitScr;
603 11 : if (which_type == TxoutType::PUBKEY) {
604 1 : segwitScr = GetScriptForDestination(WitnessV0KeyHash(Hash160(solutions_data[0])));
605 11 : } else if (which_type == TxoutType::PUBKEYHASH) {
606 4 : segwitScr = GetScriptForDestination(WitnessV0KeyHash(uint160{solutions_data[0]}));
607 4 : } else {
608 : // Scripts that are not fit for P2WPKH are encoded as P2WSH.
609 : // Newer segwit program versions should be considered when then become available.
610 6 : segwitScr = GetScriptForDestination(WitnessV0ScriptHash(script));
611 : }
612 11 : ScriptPubKeyToUniv(segwitScr, sr, /* fIncludeHex */ true);
613 11 : sr.pushKV("p2sh-segwit", EncodeDestination(ScriptHash(segwitScr)));
614 11 : r.pushKV("segwit", sr);
615 13 : }
616 : }
617 :
618 19 : return r;
619 69 : }
620 :
621 5 : static UniValue combinerawtransaction(const JSONRPCRequest& request)
622 : {
623 15 : RPCHelpMan{"combinerawtransaction",
624 5 : "\nCombine multiple partially signed transactions into one transaction.\n"
625 : "The combined transaction may be another partially signed transaction or a \n"
626 : "fully signed transaction.",
627 10 : {
628 10 : {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The hex strings of partially signed transactions",
629 10 : {
630 5 : {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A hex-encoded raw transaction"},
631 : },
632 : },
633 : },
634 5 : RPCResult{
635 5 : RPCResult::Type::STR, "", "The hex-encoded raw transaction with signature(s)"
636 : },
637 5 : RPCExamples{
638 5 : HelpExampleCli("combinerawtransaction", R"('["myhex1", "myhex2", "myhex3"]')")
639 : },
640 5 : }.Check(request);
641 :
642 :
643 1 : UniValue txs = request.params[0].get_array();
644 1 : std::vector<CMutableTransaction> txVariants(txs.size());
645 :
646 3 : for (unsigned int idx = 0; idx < txs.size(); idx++) {
647 2 : if (!DecodeHexTx(txVariants[idx], txs[idx].get_str(), true)) {
648 0 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed for tx %d", idx));
649 : }
650 : }
651 :
652 1 : if (txVariants.empty()) {
653 0 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transactions");
654 : }
655 :
656 : // mergedTx will end up with all the signatures; it
657 : // starts as a clone of the rawtx:
658 1 : CMutableTransaction mergedTx(txVariants[0]);
659 :
660 : // Fetch previous transactions (inputs):
661 1 : CCoinsView viewDummy;
662 1 : CCoinsViewCache view(&viewDummy);
663 : {
664 1 : const CTxMemPool& mempool = EnsureMemPool(request.context);
665 1 : LOCK(cs_main);
666 1 : LOCK(mempool.cs);
667 1 : CCoinsViewCache &viewChain = ::ChainstateActive().CoinsTip();
668 1 : CCoinsViewMemPool viewMempool(&viewChain, mempool);
669 1 : view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
670 :
671 2 : for (const CTxIn& txin : mergedTx.vin) {
672 1 : view.AccessCoin(txin.prevout); // Load entries from viewChain into view; can fail.
673 : }
674 :
675 1 : view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long
676 1 : }
677 :
678 : // Use CTransaction for the constant parts of the
679 : // transaction to avoid rehashing.
680 1 : const CTransaction txConst(mergedTx);
681 : // Sign what we can:
682 2 : for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
683 1 : CTxIn& txin = mergedTx.vin[i];
684 1 : const Coin& coin = view.AccessCoin(txin.prevout);
685 1 : if (coin.IsSpent()) {
686 0 : throw JSONRPCError(RPC_VERIFY_ERROR, "Input not found or already spent");
687 : }
688 1 : SignatureData sigdata;
689 :
690 : // ... and merge in other signatures:
691 3 : for (const CMutableTransaction& txv : txVariants) {
692 2 : if (txv.vin.size() > i) {
693 2 : sigdata.MergeSignatureData(DataFromTransaction(txv, i, coin.out));
694 2 : }
695 : }
696 1 : ProduceSignature(DUMMY_SIGNING_PROVIDER, MutableTransactionSignatureCreator(&mergedTx, i, coin.out.nValue, 1), coin.out.scriptPubKey, sigdata);
697 :
698 1 : UpdateInput(txin, sigdata);
699 1 : }
700 :
701 1 : return EncodeHexTx(CTransaction(mergedTx));
702 29 : }
703 :
704 209 : static UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
705 : {
706 3649 : RPCHelpMan{"signrawtransactionwithkey",
707 209 : "\nSign inputs for raw transaction (serialized, hex-encoded).\n"
708 : "The second argument is an array of base58-encoded private\n"
709 : "keys that will be the only keys used to sign the transaction.\n"
710 : "The third optional argument (may be null) is an array of previous transaction outputs that\n"
711 : "this transaction depends on but may not yet be in the block chain.\n",
712 1073 : {
713 209 : {"hexstring", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction hex string"},
714 418 : {"privkeys", RPCArg::Type::ARR, RPCArg::Optional::NO, "The base58-encoded private keys for signing",
715 418 : {
716 209 : {"privatekey", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "private key in base58-encoding"},
717 : },
718 : },
719 418 : {"prevtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "The previous dependent transaction outputs",
720 418 : {
721 418 : {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
722 1467 : {
723 209 : {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
724 209 : {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
725 209 : {"scriptPubKey", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "script key"},
726 209 : {"redeemScript", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "(required for P2SH) redeem script"},
727 209 : {"witnessScript", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "(required for P2WSH or P2SH-P2WSH) witness script"},
728 209 : {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::OMITTED, "(required for Segwit inputs) the amount spent"},
729 : },
730 : },
731 : },
732 : },
733 209 : {"sighashtype", RPCArg::Type::STR, /* default */ "ALL", "The signature hash type. Must be one of:\n"
734 : " \"ALL\"\n"
735 : " \"NONE\"\n"
736 : " \"SINGLE\"\n"
737 : " \"ALL|ANYONECANPAY\"\n"
738 : " \"NONE|ANYONECANPAY\"\n"
739 : " \"SINGLE|ANYONECANPAY\"\n"
740 : },
741 : },
742 209 : RPCResult{
743 209 : RPCResult::Type::OBJ, "", "",
744 840 : {
745 209 : {RPCResult::Type::STR_HEX, "hex", "The hex-encoded raw transaction with signature(s)"},
746 209 : {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
747 418 : {RPCResult::Type::ARR, "errors", /* optional */ true, "Script verification errors (if there are any)",
748 418 : {
749 418 : {RPCResult::Type::OBJ, "", "",
750 1258 : {
751 209 : {RPCResult::Type::STR_HEX, "txid", "The hash of the referenced, previous transaction"},
752 209 : {RPCResult::Type::NUM, "vout", "The index of the output to spent and used as input"},
753 209 : {RPCResult::Type::STR_HEX, "scriptSig", "The hex-encoded signature script"},
754 209 : {RPCResult::Type::NUM, "sequence", "Script sequence number"},
755 209 : {RPCResult::Type::STR, "error", "Verification or signing error related to the input"},
756 : }},
757 : }},
758 : }
759 : },
760 209 : RPCExamples{
761 209 : HelpExampleCli("signrawtransactionwithkey", "\"myhex\" \"[\\\"key1\\\",\\\"key2\\\"]\"")
762 209 : + HelpExampleRpc("signrawtransactionwithkey", "\"myhex\", \"[\\\"key1\\\",\\\"key2\\\"]\"")
763 : },
764 209 : }.Check(request);
765 :
766 205 : RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VARR, UniValue::VSTR}, true);
767 :
768 205 : CMutableTransaction mtx;
769 205 : if (!DecodeHexTx(mtx, request.params[0].get_str(), true)) {
770 0 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
771 : }
772 :
773 205 : FillableSigningProvider keystore;
774 205 : const UniValue& keys = request.params[1].get_array();
775 495 : for (unsigned int idx = 0; idx < keys.size(); ++idx) {
776 290 : UniValue k = keys[idx];
777 290 : CKey key = DecodeSecret(k.get_str());
778 290 : if (!key.IsValid()) {
779 0 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
780 : }
781 290 : keystore.AddKey(key);
782 290 : }
783 :
784 : // Fetch previous transactions (inputs):
785 205 : std::map<COutPoint, Coin> coins;
786 413 : for (const CTxIn& txin : mtx.vin) {
787 208 : coins[txin.prevout]; // Create empty map entry keyed by prevout.
788 : }
789 205 : NodeContext& node = EnsureNodeContext(request.context);
790 205 : FindCoins(node, coins);
791 :
792 : // Parse the prevtxs array
793 205 : ParsePrevouts(request.params[2], &keystore, coins);
794 :
795 109 : UniValue result(UniValue::VOBJ);
796 109 : SignTransaction(mtx, &keystore, coins, request.params[3], result);
797 : return result;
798 313 : }
799 :
800 8149 : static UniValue sendrawtransaction(const JSONRPCRequest& request)
801 : {
802 33011 : RPCHelpMan{"sendrawtransaction",
803 8149 : "\nSubmit a raw transaction (serialized, hex-encoded) to local node and network.\n"
804 : "\nNote that the transaction will be sent unconditionally to all peers, so using this\n"
805 : "for manual rebroadcast may degrade privacy by leaking the transaction's origin, as\n"
806 : "nodes will normally not rebroadcast non-wallet transactions already in their mempool.\n"
807 : "\nAlso see createrawtransaction and signrawtransactionwithkey calls.\n",
808 24452 : {
809 8149 : {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex string of the raw transaction"},
810 16298 : {"maxfeerate", RPCArg::Type::AMOUNT, /* default */ FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK()),
811 8149 : "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT +
812 : "/kB.\nSet to 0 to accept any fee rate.\n"},
813 : },
814 8149 : RPCResult{
815 8149 : RPCResult::Type::STR_HEX, "", "The transaction hash in hex"
816 : },
817 8149 : RPCExamples{
818 8149 : "\nCreate a transaction\n"
819 8149 : + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") +
820 : "Sign the transaction, and get back the hex\n"
821 8149 : + HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
822 : "\nSend the transaction (signed hex)\n"
823 8149 : + HelpExampleCli("sendrawtransaction", "\"signedhex\"") +
824 : "\nAs a JSON-RPC call\n"
825 8149 : + HelpExampleRpc("sendrawtransaction", "\"signedhex\"")
826 : },
827 8149 : }.Check(request);
828 :
829 24432 : RPCTypeCheck(request.params, {
830 8144 : UniValue::VSTR,
831 8144 : UniValueType(), // VNUM or VSTR, checked inside AmountFromValue()
832 : });
833 :
834 : // parse hex string from parameter
835 8144 : CMutableTransaction mtx;
836 8144 : if (!DecodeHexTx(mtx, request.params[0].get_str()))
837 2 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
838 8142 : CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
839 :
840 8142 : const CFeeRate max_raw_tx_fee_rate = request.params[1].isNull() ?
841 1013 : DEFAULT_MAX_RAW_TX_FEE_RATE :
842 7129 : CFeeRate(AmountFromValue(request.params[1]));
843 :
844 8142 : int64_t virtual_size = GetVirtualTransactionSize(*tx);
845 8142 : CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size);
846 :
847 8142 : std::string err_string;
848 8142 : AssertLockNotHeld(cs_main);
849 8142 : NodeContext& node = EnsureNodeContext(request.context);
850 8142 : const TransactionError err = BroadcastTransaction(node, tx, err_string, max_raw_tx_fee, /*relay*/ true, /*wait_callback*/ true);
851 8142 : if (TransactionError::OK != err) {
852 413 : throw JSONRPCTransactionError(err, err_string);
853 : }
854 :
855 7729 : return tx->GetHash().GetHex();
856 8169 : }
857 :
858 47 : static UniValue testmempoolaccept(const JSONRPCRequest& request)
859 : {
860 285 : RPCHelpMan{"testmempoolaccept",
861 47 : "\nReturns result of mempool acceptance tests indicating if raw transaction (serialized, hex-encoded) would be accepted by mempool.\n"
862 : "\nThis checks if the transaction violates the consensus or policy rules.\n"
863 : "\nSee sendrawtransaction call.\n",
864 153 : {
865 94 : {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of hex strings of raw transactions.\n"
866 : " Length must be one for now.",
867 94 : {
868 47 : {"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
869 : },
870 : },
871 47 : {"maxfeerate", RPCArg::Type::AMOUNT, /* default */ FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK()), "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT + "/kB\n"},
872 : },
873 47 : RPCResult{
874 47 : RPCResult::Type::ARR, "", "The result of the mempool acceptance test for each raw transaction in the input array.\n"
875 : "Length is exactly one for now.",
876 94 : {
877 94 : {RPCResult::Type::OBJ, "", "",
878 192 : {
879 47 : {RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
880 47 : {RPCResult::Type::BOOL, "allowed", "If the mempool allows this tx to be inserted"},
881 47 : {RPCResult::Type::STR, "reject-reason", "Rejection string (only present when 'allowed' is false)"},
882 : }},
883 : }
884 : },
885 47 : RPCExamples{
886 47 : "\nCreate a transaction\n"
887 47 : + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") +
888 : "Sign the transaction, and get back the hex\n"
889 47 : + HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
890 : "\nTest acceptance of the transaction (signed hex)\n"
891 47 : + HelpExampleCli("testmempoolaccept", R"('["signedhex"]')") +
892 : "\nAs a JSON-RPC call\n"
893 47 : + HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]")
894 : },
895 47 : }.Check(request);
896 :
897 129 : RPCTypeCheck(request.params, {
898 43 : UniValue::VARR,
899 43 : UniValueType(), // VNUM or VSTR, checked inside AmountFromValue()
900 : });
901 :
902 42 : if (request.params[0].get_array().size() != 1) {
903 1 : throw JSONRPCError(RPC_INVALID_PARAMETER, "Array must contain exactly one raw transaction for now");
904 : }
905 :
906 41 : CMutableTransaction mtx;
907 41 : if (!DecodeHexTx(mtx, request.params[0].get_array()[0].get_str())) {
908 1 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
909 : }
910 40 : CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
911 40 : const uint256& tx_hash = tx->GetHash();
912 :
913 40 : const CFeeRate max_raw_tx_fee_rate = request.params[1].isNull() ?
914 32 : DEFAULT_MAX_RAW_TX_FEE_RATE :
915 8 : CFeeRate(AmountFromValue(request.params[1]));
916 :
917 40 : CTxMemPool& mempool = EnsureMemPool(request.context);
918 40 : int64_t virtual_size = GetVirtualTransactionSize(*tx);
919 40 : CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size);
920 :
921 40 : UniValue result(UniValue::VARR);
922 40 : UniValue result_0(UniValue::VOBJ);
923 40 : result_0.pushKV("txid", tx_hash.GetHex());
924 :
925 40 : TxValidationState state;
926 : bool test_accept_res;
927 : {
928 40 : LOCK(cs_main);
929 40 : test_accept_res = AcceptToMemoryPool(mempool, state, std::move(tx),
930 : nullptr /* plTxnReplaced */, false /* bypass_limits */, max_raw_tx_fee, /* test_accept */ true);
931 40 : }
932 40 : result_0.pushKV("allowed", test_accept_res);
933 40 : if (!test_accept_res) {
934 28 : if (state.IsInvalid()) {
935 28 : if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
936 3 : result_0.pushKV("reject-reason", "missing-inputs");
937 3 : } else {
938 25 : result_0.pushKV("reject-reason", strprintf("%s", state.GetRejectReason()));
939 : }
940 : } else {
941 0 : result_0.pushKV("reject-reason", state.GetRejectReason());
942 : }
943 : }
944 :
945 40 : result.push_back(std::move(result_0));
946 : return result;
947 91 : }
948 :
949 177 : UniValue decodepsbt(const JSONRPCRequest& request)
950 : {
951 6251 : RPCHelpMan{"decodepsbt",
952 177 : "\nReturn a JSON object representing the serialized, base64-encoded partially signed Bitcoin transaction.\n",
953 354 : {
954 177 : {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "The PSBT base64 string"},
955 : },
956 177 : RPCResult{
957 177 : RPCResult::Type::OBJ, "", "",
958 1242 : {
959 354 : {RPCResult::Type::OBJ, "tx", "The decoded network-serialized unsigned transaction.",
960 354 : {
961 177 : {RPCResult::Type::ELISION, "", "The layout is the same as the output of decoderawtransaction."},
962 : }},
963 354 : {RPCResult::Type::OBJ_DYN, "unknown", "The unknown global fields",
964 354 : {
965 177 : {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
966 : }},
967 354 : {RPCResult::Type::ARR, "inputs", "",
968 354 : {
969 354 : {RPCResult::Type::OBJ, "", "",
970 2031 : {
971 354 : {RPCResult::Type::OBJ, "non_witness_utxo", /* optional */ true, "Decoded network transaction for non-witness UTXOs",
972 354 : {
973 177 : {RPCResult::Type::ELISION, "",""},
974 : }},
975 354 : {RPCResult::Type::OBJ, "witness_utxo", /* optional */ true, "Transaction output for witness UTXOs",
976 535 : {
977 177 : {RPCResult::Type::NUM, "amount", "The value in " + CURRENCY_UNIT},
978 354 : {RPCResult::Type::OBJ, "scriptPubKey", "",
979 889 : {
980 177 : {RPCResult::Type::STR, "asm", "The asm"},
981 177 : {RPCResult::Type::STR_HEX, "hex", "The hex"},
982 177 : {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
983 177 : {RPCResult::Type::STR, "address"," Bitcoin address if there is one"},
984 : }},
985 : }},
986 354 : {RPCResult::Type::OBJ_DYN, "partial_signatures", /* optional */ true, "",
987 354 : {
988 177 : {RPCResult::Type::STR, "pubkey", "The public key and signature that corresponds to it."},
989 : }},
990 177 : {RPCResult::Type::STR, "sighash", /* optional */ true, "The sighash type to be used"},
991 354 : {RPCResult::Type::OBJ, "redeem_script", /* optional */ true, "",
992 712 : {
993 177 : {RPCResult::Type::STR, "asm", "The asm"},
994 177 : {RPCResult::Type::STR_HEX, "hex", "The hex"},
995 177 : {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
996 : }},
997 354 : {RPCResult::Type::OBJ, "witness_script", /* optional */ true, "",
998 712 : {
999 177 : {RPCResult::Type::STR, "asm", "The asm"},
1000 177 : {RPCResult::Type::STR_HEX, "hex", "The hex"},
1001 177 : {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
1002 : }},
1003 354 : {RPCResult::Type::ARR, "bip32_derivs", /* optional */ true, "",
1004 354 : {
1005 354 : {RPCResult::Type::OBJ, "pubkey", /* optional */ true, "The public key with the derivation path as the value.",
1006 535 : {
1007 177 : {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
1008 177 : {RPCResult::Type::STR, "path", "The path"},
1009 : }},
1010 : }},
1011 354 : {RPCResult::Type::OBJ, "final_scriptsig", /* optional */ true, "",
1012 535 : {
1013 177 : {RPCResult::Type::STR, "asm", "The asm"},
1014 177 : {RPCResult::Type::STR, "hex", "The hex"},
1015 : }},
1016 354 : {RPCResult::Type::ARR, "final_scriptwitness", "",
1017 354 : {
1018 177 : {RPCResult::Type::STR_HEX, "", "hex-encoded witness data (if any)"},
1019 : }},
1020 354 : {RPCResult::Type::OBJ_DYN, "unknown", "The unknown global fields",
1021 354 : {
1022 177 : {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
1023 : }},
1024 : }},
1025 : }},
1026 354 : {RPCResult::Type::ARR, "outputs", "",
1027 354 : {
1028 354 : {RPCResult::Type::OBJ, "", "",
1029 921 : {
1030 354 : {RPCResult::Type::OBJ, "redeem_script", /* optional */ true, "",
1031 712 : {
1032 177 : {RPCResult::Type::STR, "asm", "The asm"},
1033 177 : {RPCResult::Type::STR_HEX, "hex", "The hex"},
1034 177 : {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
1035 : }},
1036 354 : {RPCResult::Type::OBJ, "witness_script", /* optional */ true, "",
1037 712 : {
1038 177 : {RPCResult::Type::STR, "asm", "The asm"},
1039 177 : {RPCResult::Type::STR_HEX, "hex", "The hex"},
1040 177 : {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
1041 : }},
1042 354 : {RPCResult::Type::ARR, "bip32_derivs", /* optional */ true, "",
1043 354 : {
1044 354 : {RPCResult::Type::OBJ, "", "",
1045 712 : {
1046 177 : {RPCResult::Type::STR, "pubkey", "The public key this path corresponds to"},
1047 177 : {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
1048 177 : {RPCResult::Type::STR, "path", "The path"},
1049 : }},
1050 : }},
1051 354 : {RPCResult::Type::OBJ_DYN, "unknown", "The unknown global fields",
1052 354 : {
1053 177 : {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
1054 : }},
1055 : }},
1056 : }},
1057 177 : {RPCResult::Type::STR_AMOUNT, "fee", /* optional */ true, "The transaction fee paid if all UTXOs slots in the PSBT have been filled."},
1058 : }
1059 : },
1060 177 : RPCExamples{
1061 177 : HelpExampleCli("decodepsbt", "\"psbt\"")
1062 : },
1063 177 : }.Check(request);
1064 :
1065 173 : RPCTypeCheck(request.params, {UniValue::VSTR});
1066 :
1067 : // Unserialize the transactions
1068 173 : PartiallySignedTransaction psbtx;
1069 173 : std::string error;
1070 173 : if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
1071 56 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
1072 : }
1073 :
1074 117 : UniValue result(UniValue::VOBJ);
1075 :
1076 : // Add the decoded tx
1077 117 : UniValue tx_univ(UniValue::VOBJ);
1078 117 : TxToUniv(CTransaction(*psbtx.tx), uint256(), tx_univ, false);
1079 117 : result.pushKV("tx", tx_univ);
1080 :
1081 : // Unknown data
1082 117 : UniValue unknowns(UniValue::VOBJ);
1083 117 : for (auto entry : psbtx.unknown) {
1084 0 : unknowns.pushKV(HexStr(entry.first), HexStr(entry.second));
1085 0 : }
1086 117 : result.pushKV("unknown", unknowns);
1087 :
1088 : // inputs
1089 : CAmount total_in = 0;
1090 546 : bool have_all_utxos = true;
1091 117 : UniValue inputs(UniValue::VARR);
1092 275 : for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {
1093 158 : const PSBTInput& input = psbtx.inputs[i];
1094 158 : UniValue in(UniValue::VOBJ);
1095 : // UTXOs
1096 : bool have_a_utxo = false;
1097 158 : CTxOut txout;
1098 158 : if (!input.witness_utxo.IsNull()) {
1099 92 : txout = input.witness_utxo;
1100 :
1101 92 : UniValue o(UniValue::VOBJ);
1102 92 : ScriptToUniv(txout.scriptPubKey, o, true);
1103 :
1104 92 : UniValue out(UniValue::VOBJ);
1105 92 : out.pushKV("amount", ValueFromAmount(txout.nValue));
1106 92 : out.pushKV("scriptPubKey", o);
1107 :
1108 92 : in.pushKV("witness_utxo", out);
1109 :
1110 : have_a_utxo = true;
1111 92 : }
1112 158 : if (input.non_witness_utxo) {
1113 118 : txout = input.non_witness_utxo->vout[psbtx.tx->vin[i].prevout.n];
1114 :
1115 118 : UniValue non_wit(UniValue::VOBJ);
1116 118 : TxToUniv(*input.non_witness_utxo, uint256(), non_wit, false);
1117 118 : in.pushKV("non_witness_utxo", non_wit);
1118 :
1119 : have_a_utxo = true;
1120 118 : }
1121 158 : if (have_a_utxo) {
1122 130 : if (MoneyRange(txout.nValue) && MoneyRange(total_in + txout.nValue)) {
1123 130 : total_in += txout.nValue;
1124 130 : } else {
1125 : // Hack to just not show fee later
1126 : have_all_utxos = false;
1127 : }
1128 : } else {
1129 : have_all_utxos = false;
1130 : }
1131 :
1132 : // Partial sigs
1133 158 : if (!input.partial_sigs.empty()) {
1134 2 : UniValue partial_sigs(UniValue::VOBJ);
1135 4 : for (const auto& sig : input.partial_sigs) {
1136 2 : partial_sigs.pushKV(HexStr(sig.second.first), HexStr(sig.second.second));
1137 0 : }
1138 2 : in.pushKV("partial_signatures", partial_sigs);
1139 2 : }
1140 :
1141 : // Sighash
1142 158 : if (input.sighash_type > 0) {
1143 2 : in.pushKV("sighash", SighashToStr((unsigned char)input.sighash_type));
1144 2 : }
1145 :
1146 : // Redeem script and witness script
1147 158 : if (!input.redeem_script.empty()) {
1148 47 : UniValue r(UniValue::VOBJ);
1149 47 : ScriptToUniv(input.redeem_script, r, false);
1150 47 : in.pushKV("redeem_script", r);
1151 47 : }
1152 158 : if (!input.witness_script.empty()) {
1153 26 : UniValue r(UniValue::VOBJ);
1154 26 : ScriptToUniv(input.witness_script, r, false);
1155 26 : in.pushKV("witness_script", r);
1156 26 : }
1157 :
1158 : // keypaths
1159 158 : if (!input.hd_keypaths.empty()) {
1160 93 : UniValue keypaths(UniValue::VARR);
1161 220 : for (auto entry : input.hd_keypaths) {
1162 127 : UniValue keypath(UniValue::VOBJ);
1163 127 : keypath.pushKV("pubkey", HexStr(entry.first));
1164 :
1165 127 : keypath.pushKV("master_fingerprint", strprintf("%08x", ReadBE32(entry.second.fingerprint)));
1166 127 : keypath.pushKV("path", WriteHDKeypath(entry.second.path));
1167 127 : keypaths.push_back(keypath);
1168 127 : }
1169 93 : in.pushKV("bip32_derivs", keypaths);
1170 93 : }
1171 :
1172 : // Final scriptSig and scriptwitness
1173 158 : if (!input.final_script_sig.empty()) {
1174 14 : UniValue scriptsig(UniValue::VOBJ);
1175 14 : scriptsig.pushKV("asm", ScriptToAsmStr(input.final_script_sig, true));
1176 14 : scriptsig.pushKV("hex", HexStr(input.final_script_sig));
1177 14 : in.pushKV("final_scriptSig", scriptsig);
1178 14 : }
1179 158 : if (!input.final_script_witness.IsNull()) {
1180 9 : UniValue txinwitness(UniValue::VARR);
1181 27 : for (const auto& item : input.final_script_witness.stack) {
1182 18 : txinwitness.push_back(HexStr(item));
1183 : }
1184 9 : in.pushKV("final_scriptwitness", txinwitness);
1185 9 : }
1186 :
1187 : // Unknown data
1188 158 : if (input.unknown.size() > 0) {
1189 0 : UniValue unknowns(UniValue::VOBJ);
1190 0 : for (auto entry : input.unknown) {
1191 0 : unknowns.pushKV(HexStr(entry.first), HexStr(entry.second));
1192 0 : }
1193 0 : in.pushKV("unknown", unknowns);
1194 0 : }
1195 :
1196 158 : inputs.push_back(in);
1197 158 : }
1198 117 : result.pushKV("inputs", inputs);
1199 :
1200 : // outputs
1201 : CAmount output_value = 0;
1202 117 : UniValue outputs(UniValue::VARR);
1203 271 : for (unsigned int i = 0; i < psbtx.outputs.size(); ++i) {
1204 154 : const PSBTOutput& output = psbtx.outputs[i];
1205 154 : UniValue out(UniValue::VOBJ);
1206 : // Redeem script and witness script
1207 154 : if (!output.redeem_script.empty()) {
1208 39 : UniValue r(UniValue::VOBJ);
1209 39 : ScriptToUniv(output.redeem_script, r, false);
1210 39 : out.pushKV("redeem_script", r);
1211 39 : }
1212 154 : if (!output.witness_script.empty()) {
1213 24 : UniValue r(UniValue::VOBJ);
1214 24 : ScriptToUniv(output.witness_script, r, false);
1215 24 : out.pushKV("witness_script", r);
1216 24 : }
1217 :
1218 : // keypaths
1219 154 : if (!output.hd_keypaths.empty()) {
1220 86 : UniValue keypaths(UniValue::VARR);
1221 204 : for (auto entry : output.hd_keypaths) {
1222 118 : UniValue keypath(UniValue::VOBJ);
1223 118 : keypath.pushKV("pubkey", HexStr(entry.first));
1224 118 : keypath.pushKV("master_fingerprint", strprintf("%08x", ReadBE32(entry.second.fingerprint)));
1225 118 : keypath.pushKV("path", WriteHDKeypath(entry.second.path));
1226 118 : keypaths.push_back(keypath);
1227 118 : }
1228 86 : out.pushKV("bip32_derivs", keypaths);
1229 86 : }
1230 :
1231 : // Unknown data
1232 154 : if (output.unknown.size() > 0) {
1233 0 : UniValue unknowns(UniValue::VOBJ);
1234 0 : for (auto entry : output.unknown) {
1235 0 : unknowns.pushKV(HexStr(entry.first), HexStr(entry.second));
1236 0 : }
1237 0 : out.pushKV("unknown", unknowns);
1238 0 : }
1239 :
1240 154 : outputs.push_back(out);
1241 :
1242 : // Fee calculation
1243 154 : if (MoneyRange(psbtx.tx->vout[i].nValue) && MoneyRange(output_value + psbtx.tx->vout[i].nValue)) {
1244 154 : output_value += psbtx.tx->vout[i].nValue;
1245 154 : } else {
1246 : // Hack to just not show fee later
1247 : have_all_utxos = false;
1248 : }
1249 154 : }
1250 117 : result.pushKV("outputs", outputs);
1251 117 : if (have_all_utxos) {
1252 99 : result.pushKV("fee", ValueFromAmount(total_in - output_value));
1253 99 : }
1254 :
1255 : return result;
1256 373 : }
1257 :
1258 12 : UniValue combinepsbt(const JSONRPCRequest& request)
1259 : {
1260 38 : RPCHelpMan{"combinepsbt",
1261 12 : "\nCombine multiple partially signed Bitcoin transactions into one transaction.\n"
1262 : "Implements the Combiner role.\n",
1263 24 : {
1264 24 : {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The base64 strings of partially signed transactions",
1265 24 : {
1266 12 : {"psbt", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A base64 string of a PSBT"},
1267 : },
1268 : },
1269 : },
1270 12 : RPCResult{
1271 12 : RPCResult::Type::STR, "", "The base64-encoded partially signed transaction"
1272 : },
1273 12 : RPCExamples{
1274 12 : HelpExampleCli("combinepsbt", R"('["mybase64_1", "mybase64_2", "mybase64_3"]')")
1275 : },
1276 12 : }.Check(request);
1277 :
1278 8 : RPCTypeCheck(request.params, {UniValue::VARR}, true);
1279 :
1280 : // Unserialize the transactions
1281 8 : std::vector<PartiallySignedTransaction> psbtxs;
1282 8 : UniValue txs = request.params[0].get_array();
1283 8 : if (txs.empty()) {
1284 2 : throw JSONRPCError(RPC_INVALID_PARAMETER, "Parameter 'txs' cannot be empty");
1285 : }
1286 18 : for (unsigned int i = 0; i < txs.size(); ++i) {
1287 12 : PartiallySignedTransaction psbtx;
1288 12 : std::string error;
1289 12 : if (!DecodeBase64PSBT(psbtx, txs[i].get_str(), error)) {
1290 0 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
1291 : }
1292 12 : psbtxs.push_back(psbtx);
1293 12 : }
1294 :
1295 6 : PartiallySignedTransaction merged_psbt;
1296 6 : const TransactionError error = CombinePSBTs(merged_psbt, psbtxs);
1297 6 : if (error != TransactionError::OK) {
1298 0 : throw JSONRPCTransactionError(error);
1299 : }
1300 :
1301 6 : CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
1302 6 : ssTx << merged_psbt;
1303 6 : return EncodeBase64(MakeUCharSpan(ssTx));
1304 36 : }
1305 :
1306 19 : UniValue finalizepsbt(const JSONRPCRequest& request)
1307 : {
1308 114 : RPCHelpMan{"finalizepsbt",
1309 19 : "Finalize the inputs of a PSBT. If the transaction is fully signed, it will produce a\n"
1310 : "network serialized transaction which can be broadcast with sendrawtransaction. Otherwise a PSBT will be\n"
1311 : "created which has the final_scriptSig and final_scriptWitness fields filled for inputs that are complete.\n"
1312 : "Implements the Finalizer and Extractor roles.\n",
1313 61 : {
1314 19 : {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"},
1315 19 : {"extract", RPCArg::Type::BOOL, /* default */ "true", "If true and the transaction is complete,\n"
1316 : " extract and return the complete transaction in normal network serialization instead of the PSBT."},
1317 : },
1318 19 : RPCResult{
1319 19 : RPCResult::Type::OBJ, "", "",
1320 80 : {
1321 19 : {RPCResult::Type::STR, "psbt", "The base64-encoded partially signed transaction if not extracted"},
1322 19 : {RPCResult::Type::STR_HEX, "hex", "The hex-encoded network transaction if extracted"},
1323 19 : {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
1324 : }
1325 : },
1326 19 : RPCExamples{
1327 19 : HelpExampleCli("finalizepsbt", "\"psbt\"")
1328 : },
1329 19 : }.Check(request);
1330 :
1331 15 : RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}, true);
1332 :
1333 : // Unserialize the transactions
1334 15 : PartiallySignedTransaction psbtx;
1335 15 : std::string error;
1336 15 : if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
1337 0 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
1338 : }
1339 :
1340 15 : bool extract = request.params[1].isNull() || (!request.params[1].isNull() && request.params[1].get_bool());
1341 :
1342 15 : CMutableTransaction mtx;
1343 15 : bool complete = FinalizeAndExtractPSBT(psbtx, mtx);
1344 :
1345 15 : UniValue result(UniValue::VOBJ);
1346 15 : CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
1347 15 : std::string result_str;
1348 :
1349 15 : if (complete && extract) {
1350 12 : ssTx << mtx;
1351 12 : result_str = HexStr(ssTx);
1352 12 : result.pushKV("hex", result_str);
1353 12 : } else {
1354 3 : ssTx << psbtx;
1355 3 : result_str = EncodeBase64(ssTx.str());
1356 3 : result.pushKV("psbt", result_str);
1357 : }
1358 15 : result.pushKV("complete", complete);
1359 :
1360 : return result;
1361 43 : }
1362 :
1363 80 : UniValue createpsbt(const JSONRPCRequest& request)
1364 : {
1365 720 : RPCHelpMan{"createpsbt",
1366 80 : "\nCreates a transaction in the Partially Signed Transaction format.\n"
1367 : "Implements the Creator role.\n",
1368 444 : {
1369 160 : {"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The json objects",
1370 160 : {
1371 160 : {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
1372 324 : {
1373 80 : {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
1374 80 : {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
1375 80 : {"sequence", RPCArg::Type::NUM, /* default */ "depends on the value of the 'replaceable' and 'locktime' arguments", "The sequence number"},
1376 : },
1377 : },
1378 : },
1379 : },
1380 160 : {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The outputs (key-value pairs), where none of the keys are duplicated.\n"
1381 : "That is, each address can only appear once and there can only be one 'data' object.\n"
1382 : "For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n"
1383 : " accepted as second parameter.",
1384 252 : {
1385 160 : {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
1386 160 : {
1387 80 : {"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},
1388 : },
1389 : },
1390 160 : {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
1391 160 : {
1392 80 : {"data", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A key-value pair. The key must be \"data\", the value is hex-encoded data"},
1393 : },
1394 : },
1395 : },
1396 : },
1397 80 : {"locktime", RPCArg::Type::NUM, /* default */ "0", "Raw locktime. Non-0 value also locktime-activates inputs"},
1398 80 : {"replaceable", RPCArg::Type::BOOL, /* default */ "false", "Marks this transaction as BIP125 replaceable.\n"
1399 : " Allows this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible."},
1400 : },
1401 80 : RPCResult{
1402 80 : RPCResult::Type::STR, "", "The resulting raw transaction (base64-encoded string)"
1403 : },
1404 80 : RPCExamples{
1405 80 : HelpExampleCli("createpsbt", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"")
1406 : },
1407 80 : }.Check(request);
1408 :
1409 :
1410 380 : RPCTypeCheck(request.params, {
1411 76 : UniValue::VARR,
1412 76 : UniValueType(), // ARR or OBJ, checked later
1413 76 : UniValue::VNUM,
1414 76 : UniValue::VBOOL,
1415 : }, true
1416 : );
1417 :
1418 : bool rbf = false;
1419 76 : if (!request.params[3].isNull()) {
1420 0 : rbf = request.params[3].isTrue();
1421 0 : }
1422 76 : CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], rbf);
1423 :
1424 : // Make a blank psbt
1425 76 : PartiallySignedTransaction psbtx;
1426 76 : psbtx.tx = rawTx;
1427 160 : for (unsigned int i = 0; i < rawTx.vin.size(); ++i) {
1428 84 : psbtx.inputs.push_back(PSBTInput());
1429 : }
1430 154 : for (unsigned int i = 0; i < rawTx.vout.size(); ++i) {
1431 78 : psbtx.outputs.push_back(PSBTOutput());
1432 : }
1433 :
1434 : // Serialize the PSBT
1435 76 : CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
1436 76 : ssTx << psbtx;
1437 :
1438 76 : return EncodeBase64(MakeUCharSpan(ssTx));
1439 176 : }
1440 :
1441 14 : UniValue converttopsbt(const JSONRPCRequest& request)
1442 : {
1443 74 : RPCHelpMan{"converttopsbt",
1444 14 : "\nConverts a network serialized transaction to a PSBT. This should be used only with createrawtransaction and fundrawtransaction\n"
1445 : "createpsbt and walletcreatefundedpsbt should be used for new applications.\n",
1446 60 : {
1447 14 : {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex string of a raw transaction"},
1448 14 : {"permitsigdata", RPCArg::Type::BOOL, /* default */ "false", "If true, any signatures in the input will be discarded and conversion\n"
1449 : " will continue. If false, RPC will fail if any signatures are present."},
1450 14 : {"iswitness", RPCArg::Type::BOOL, /* default */ "depends on heuristic tests", "Whether the transaction hex is a serialized witness transaction.\n"
1451 : "If iswitness is not present, heuristic tests will be used in decoding.\n"
1452 : "If true, only witness deserialization will be tried.\n"
1453 : "If false, only non-witness deserialization will be tried.\n"
1454 : "This boolean should reflect whether the transaction has inputs\n"
1455 : "(e.g. fully valid, or on-chain transactions), if known by the caller."
1456 : },
1457 : },
1458 14 : RPCResult{
1459 14 : RPCResult::Type::STR, "", "The resulting raw transaction (base64-encoded string)"
1460 : },
1461 14 : RPCExamples{
1462 14 : "\nCreate a transaction\n"
1463 14 : + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"") +
1464 : "\nConvert the transaction to a PSBT\n"
1465 14 : + HelpExampleCli("converttopsbt", "\"rawtransaction\"")
1466 : },
1467 14 : }.Check(request);
1468 :
1469 10 : RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL, UniValue::VBOOL}, true);
1470 :
1471 : // parse hex string from parameter
1472 10 : CMutableTransaction tx;
1473 10 : bool permitsigdata = request.params[1].isNull() ? false : request.params[1].get_bool();
1474 10 : bool witness_specified = !request.params[2].isNull();
1475 10 : bool iswitness = witness_specified ? request.params[2].get_bool() : false;
1476 10 : const bool try_witness = witness_specified ? iswitness : true;
1477 10 : const bool try_no_witness = witness_specified ? !iswitness : true;
1478 10 : if (!DecodeHexTx(tx, request.params[0].get_str(), try_no_witness, try_witness)) {
1479 0 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
1480 : }
1481 :
1482 : // Remove all scriptSigs and scriptWitnesses from inputs
1483 20 : for (CTxIn& input : tx.vin) {
1484 10 : if ((!input.scriptSig.empty() || !input.scriptWitness.IsNull()) && !permitsigdata) {
1485 4 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Inputs must not have scriptSigs and scriptWitnesses");
1486 : }
1487 6 : input.scriptSig.clear();
1488 6 : input.scriptWitness.SetNull();
1489 : }
1490 :
1491 : // Make a blank psbt
1492 6 : PartiallySignedTransaction psbtx;
1493 6 : psbtx.tx = tx;
1494 12 : for (unsigned int i = 0; i < tx.vin.size(); ++i) {
1495 6 : psbtx.inputs.push_back(PSBTInput());
1496 : }
1497 18 : for (unsigned int i = 0; i < tx.vout.size(); ++i) {
1498 12 : psbtx.outputs.push_back(PSBTOutput());
1499 : }
1500 :
1501 : // Serialize the PSBT
1502 6 : CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
1503 6 : ssTx << psbtx;
1504 :
1505 6 : return EncodeBase64(MakeUCharSpan(ssTx));
1506 38 : }
1507 :
1508 8 : UniValue utxoupdatepsbt(const JSONRPCRequest& request)
1509 : {
1510 48 : RPCHelpMan{"utxoupdatepsbt",
1511 8 : "\nUpdates all segwit inputs and outputs in a PSBT with data from output descriptors, the UTXO set or the mempool.\n",
1512 28 : {
1513 8 : {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"},
1514 28 : {"descriptors", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "An array of either strings or objects", {
1515 8 : {"", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "An output descriptor"},
1516 28 : {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "An object with an output descriptor and extra information", {
1517 8 : {"desc", RPCArg::Type::STR, RPCArg::Optional::NO, "An output descriptor"},
1518 8 : {"range", RPCArg::Type::RANGE, "1000", "Up to what index HD chains should be explored (either end or [begin,end])"},
1519 : }},
1520 : }},
1521 : },
1522 8 : RPCResult {
1523 8 : RPCResult::Type::STR, "", "The base64-encoded partially signed transaction with inputs updated"
1524 : },
1525 8 : RPCExamples {
1526 8 : HelpExampleCli("utxoupdatepsbt", "\"psbt\"")
1527 8 : }}.Check(request);
1528 :
1529 4 : RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR}, true);
1530 :
1531 : // Unserialize the transactions
1532 4 : PartiallySignedTransaction psbtx;
1533 4 : std::string error;
1534 4 : if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
1535 0 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
1536 : }
1537 :
1538 : // Parse descriptors, if any.
1539 4 : FlatSigningProvider provider;
1540 4 : if (!request.params[1].isNull()) {
1541 2 : auto descs = request.params[1].get_array();
1542 8 : for (size_t i = 0; i < descs.size(); ++i) {
1543 6 : EvalDescriptorStringOrObject(descs[i], provider);
1544 : }
1545 2 : }
1546 : // We don't actually need private keys further on; hide them as a precaution.
1547 4 : HidingSigningProvider public_provider(&provider, /* nosign */ true, /* nobip32derivs */ false);
1548 :
1549 : // Fetch previous transactions (inputs):
1550 4 : CCoinsView viewDummy;
1551 4 : CCoinsViewCache view(&viewDummy);
1552 : {
1553 4 : const CTxMemPool& mempool = EnsureMemPool(request.context);
1554 4 : LOCK2(cs_main, mempool.cs);
1555 4 : CCoinsViewCache &viewChain = ::ChainstateActive().CoinsTip();
1556 4 : CCoinsViewMemPool viewMempool(&viewChain, mempool);
1557 4 : view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
1558 :
1559 16 : for (const CTxIn& txin : psbtx.tx->vin) {
1560 12 : view.AccessCoin(txin.prevout); // Load entries from viewChain into view; can fail.
1561 : }
1562 :
1563 4 : view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long
1564 4 : }
1565 :
1566 : // Fill the inputs
1567 16 : for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
1568 12 : PSBTInput& input = psbtx.inputs.at(i);
1569 :
1570 12 : if (input.non_witness_utxo || !input.witness_utxo.IsNull()) {
1571 0 : continue;
1572 : }
1573 :
1574 12 : const Coin& coin = view.AccessCoin(psbtx.tx->vin[i].prevout);
1575 :
1576 12 : if (IsSegWitOutput(provider, coin.out.scriptPubKey)) {
1577 6 : input.witness_utxo = coin.out;
1578 : }
1579 :
1580 : // Update script/keypath information using descriptor data.
1581 : // Note that SignPSBTInput does a lot more than just constructing ECDSA signatures
1582 : // we don't actually care about those here, in fact.
1583 12 : SignPSBTInput(public_provider, psbtx, i, /* sighash_type */ 1);
1584 12 : }
1585 :
1586 : // Update script/keypath information using descriptor data.
1587 8 : for (unsigned int i = 0; i < psbtx.tx->vout.size(); ++i) {
1588 4 : UpdatePSBTOutput(public_provider, psbtx, i);
1589 : }
1590 :
1591 4 : CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
1592 4 : ssTx << psbtx;
1593 4 : return EncodeBase64(MakeUCharSpan(ssTx));
1594 56 : }
1595 :
1596 10 : UniValue joinpsbts(const JSONRPCRequest& request)
1597 : {
1598 32 : RPCHelpMan{"joinpsbts",
1599 10 : "\nJoins multiple distinct PSBTs with different inputs and outputs into one PSBT with inputs and outputs from all of the PSBTs\n"
1600 : "No input in any of the PSBTs can be in more than one of the PSBTs.\n",
1601 20 : {
1602 20 : {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The base64 strings of partially signed transactions",
1603 20 : {
1604 10 : {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"}
1605 : }}
1606 : },
1607 10 : RPCResult {
1608 10 : RPCResult::Type::STR, "", "The base64-encoded partially signed transaction"
1609 : },
1610 10 : RPCExamples {
1611 10 : HelpExampleCli("joinpsbts", "\"psbt\"")
1612 10 : }}.Check(request);
1613 :
1614 6 : RPCTypeCheck(request.params, {UniValue::VARR}, true);
1615 :
1616 : // Unserialize the transactions
1617 6 : std::vector<PartiallySignedTransaction> psbtxs;
1618 6 : UniValue txs = request.params[0].get_array();
1619 :
1620 6 : if (txs.size() <= 1) {
1621 0 : throw JSONRPCError(RPC_INVALID_PARAMETER, "At least two PSBTs are required to join PSBTs.");
1622 : }
1623 :
1624 : uint32_t best_version = 1;
1625 : uint32_t best_locktime = 0xffffffff;
1626 18 : for (unsigned int i = 0; i < txs.size(); ++i) {
1627 12 : PartiallySignedTransaction psbtx;
1628 12 : std::string error;
1629 12 : if (!DecodeBase64PSBT(psbtx, txs[i].get_str(), error)) {
1630 0 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
1631 : }
1632 12 : psbtxs.push_back(psbtx);
1633 : // Choose the highest version number
1634 12 : if (static_cast<uint32_t>(psbtx.tx->nVersion) > best_version) {
1635 6 : best_version = static_cast<uint32_t>(psbtx.tx->nVersion);
1636 6 : }
1637 : // Choose the lowest lock time
1638 12 : if (psbtx.tx->nLockTime < best_locktime) {
1639 6 : best_locktime = psbtx.tx->nLockTime;
1640 6 : }
1641 12 : }
1642 :
1643 : // Create a blank psbt where everything will be added
1644 6 : PartiallySignedTransaction merged_psbt;
1645 6 : merged_psbt.tx = CMutableTransaction();
1646 6 : merged_psbt.tx->nVersion = static_cast<int32_t>(best_version);
1647 6 : merged_psbt.tx->nLockTime = best_locktime;
1648 :
1649 : // Merge
1650 18 : for (auto& psbt : psbtxs) {
1651 32 : for (unsigned int i = 0; i < psbt.tx->vin.size(); ++i) {
1652 20 : if (!merged_psbt.AddInput(psbt.tx->vin[i], psbt.inputs[i])) {
1653 2 : throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input %s:%d exists in multiple PSBTs", psbt.tx->vin[i].prevout.hash.ToString(), psbt.tx->vin[i].prevout.n));
1654 : }
1655 : }
1656 20 : for (unsigned int i = 0; i < psbt.tx->vout.size(); ++i) {
1657 10 : merged_psbt.AddOutput(psbt.tx->vout[i], psbt.outputs[i]);
1658 : }
1659 10 : merged_psbt.unknown.insert(psbt.unknown.begin(), psbt.unknown.end());
1660 : }
1661 :
1662 : // Generate list of shuffled indices for shuffling inputs and outputs of the merged PSBT
1663 4 : std::vector<int> input_indices(merged_psbt.inputs.size());
1664 4 : std::iota(input_indices.begin(), input_indices.end(), 0);
1665 4 : std::vector<int> output_indices(merged_psbt.outputs.size());
1666 4 : std::iota(output_indices.begin(), output_indices.end(), 0);
1667 :
1668 : // Shuffle input and output indices lists
1669 4 : Shuffle(input_indices.begin(), input_indices.end(), FastRandomContext());
1670 4 : Shuffle(output_indices.begin(), output_indices.end(), FastRandomContext());
1671 :
1672 4 : PartiallySignedTransaction shuffled_psbt;
1673 4 : shuffled_psbt.tx = CMutableTransaction();
1674 4 : shuffled_psbt.tx->nVersion = merged_psbt.tx->nVersion;
1675 4 : shuffled_psbt.tx->nLockTime = merged_psbt.tx->nLockTime;
1676 20 : for (int i : input_indices) {
1677 16 : shuffled_psbt.AddInput(merged_psbt.tx->vin[i], merged_psbt.inputs[i]);
1678 : }
1679 12 : for (int i : output_indices) {
1680 8 : shuffled_psbt.AddOutput(merged_psbt.tx->vout[i], merged_psbt.outputs[i]);
1681 : }
1682 4 : shuffled_psbt.unknown.insert(merged_psbt.unknown.begin(), merged_psbt.unknown.end());
1683 :
1684 4 : CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
1685 4 : ssTx << shuffled_psbt;
1686 4 : return EncodeBase64(MakeUCharSpan(ssTx));
1687 36 : }
1688 :
1689 20 : UniValue analyzepsbt(const JSONRPCRequest& request)
1690 : {
1691 280 : RPCHelpMan{"analyzepsbt",
1692 20 : "\nAnalyzes and provides information about the current status of a PSBT and its inputs\n",
1693 40 : {
1694 20 : {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"}
1695 : },
1696 20 : RPCResult {
1697 20 : RPCResult::Type::OBJ, "", "",
1698 184 : {
1699 40 : {RPCResult::Type::ARR, "inputs", "",
1700 40 : {
1701 40 : {RPCResult::Type::OBJ, "", "",
1702 128 : {
1703 20 : {RPCResult::Type::BOOL, "has_utxo", "Whether a UTXO is provided"},
1704 20 : {RPCResult::Type::BOOL, "is_final", "Whether the input is finalized"},
1705 40 : {RPCResult::Type::OBJ, "missing", /* optional */ true, "Things that are missing that are required to complete this input",
1706 120 : {
1707 40 : {RPCResult::Type::ARR, "pubkeys", /* optional */ true, "",
1708 40 : {
1709 20 : {RPCResult::Type::STR_HEX, "keyid", "Public key ID, hash160 of the public key, of a public key whose BIP 32 derivation path is missing"},
1710 : }},
1711 40 : {RPCResult::Type::ARR, "signatures", /* optional */ true, "",
1712 40 : {
1713 20 : {RPCResult::Type::STR_HEX, "keyid", "Public key ID, hash160 of the public key, of a public key whose signature is missing"},
1714 : }},
1715 20 : {RPCResult::Type::STR_HEX, "redeemscript", /* optional */ true, "Hash160 of the redeemScript that is missing"},
1716 20 : {RPCResult::Type::STR_HEX, "witnessscript", /* optional */ true, "SHA256 of the witnessScript that is missing"},
1717 : }},
1718 20 : {RPCResult::Type::STR, "next", /* optional */ true, "Role of the next person that this input needs to go to"},
1719 : }},
1720 : }},
1721 20 : {RPCResult::Type::NUM, "estimated_vsize", /* optional */ true, "Estimated vsize of the final signed transaction"},
1722 20 : {RPCResult::Type::STR_AMOUNT, "estimated_feerate", /* optional */ true, "Estimated feerate of the final signed transaction in " + CURRENCY_UNIT + "/kB. Shown only if all UTXO slots in the PSBT have been filled"},
1723 20 : {RPCResult::Type::STR_AMOUNT, "fee", /* optional */ true, "The transaction fee paid. Shown only if all UTXO slots in the PSBT have been filled"},
1724 20 : {RPCResult::Type::STR, "next", "Role of the next person that this psbt needs to go to"},
1725 20 : {RPCResult::Type::STR, "error", /* optional */ true, "Error message (if there is one)"},
1726 : }
1727 : },
1728 20 : RPCExamples {
1729 20 : HelpExampleCli("analyzepsbt", "\"psbt\"")
1730 20 : }}.Check(request);
1731 :
1732 16 : RPCTypeCheck(request.params, {UniValue::VSTR});
1733 :
1734 : // Unserialize the transaction
1735 16 : PartiallySignedTransaction psbtx;
1736 16 : std::string error;
1737 16 : if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
1738 0 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
1739 : }
1740 :
1741 16 : PSBTAnalysis psbta = AnalyzePSBT(psbtx);
1742 :
1743 16 : UniValue result(UniValue::VOBJ);
1744 16 : UniValue inputs_result(UniValue::VARR);
1745 24 : for (const auto& input : psbta.inputs) {
1746 8 : UniValue input_univ(UniValue::VOBJ);
1747 8 : UniValue missing(UniValue::VOBJ);
1748 :
1749 8 : input_univ.pushKV("has_utxo", input.has_utxo);
1750 8 : input_univ.pushKV("is_final", input.is_final);
1751 8 : input_univ.pushKV("next", PSBTRoleName(input.next));
1752 :
1753 8 : if (!input.missing_pubkeys.empty()) {
1754 0 : UniValue missing_pubkeys_univ(UniValue::VARR);
1755 0 : for (const CKeyID& pubkey : input.missing_pubkeys) {
1756 0 : missing_pubkeys_univ.push_back(HexStr(pubkey));
1757 : }
1758 0 : missing.pushKV("pubkeys", missing_pubkeys_univ);
1759 0 : }
1760 8 : if (!input.missing_redeem_script.IsNull()) {
1761 0 : missing.pushKV("redeemscript", HexStr(input.missing_redeem_script));
1762 0 : }
1763 8 : if (!input.missing_witness_script.IsNull()) {
1764 0 : missing.pushKV("witnessscript", HexStr(input.missing_witness_script));
1765 0 : }
1766 8 : if (!input.missing_sigs.empty()) {
1767 2 : UniValue missing_sigs_univ(UniValue::VARR);
1768 4 : for (const CKeyID& pubkey : input.missing_sigs) {
1769 2 : missing_sigs_univ.push_back(HexStr(pubkey));
1770 : }
1771 2 : missing.pushKV("signatures", missing_sigs_univ);
1772 2 : }
1773 8 : if (!missing.getKeys().empty()) {
1774 2 : input_univ.pushKV("missing", missing);
1775 2 : }
1776 8 : inputs_result.push_back(input_univ);
1777 8 : }
1778 16 : if (!inputs_result.empty()) result.pushKV("inputs", inputs_result);
1779 :
1780 16 : if (psbta.estimated_vsize != nullopt) {
1781 6 : result.pushKV("estimated_vsize", (int)*psbta.estimated_vsize);
1782 6 : }
1783 16 : if (psbta.estimated_feerate != nullopt) {
1784 6 : result.pushKV("estimated_feerate", ValueFromAmount(psbta.estimated_feerate->GetFeePerK()));
1785 6 : }
1786 16 : if (psbta.fee != nullopt) {
1787 6 : result.pushKV("fee", ValueFromAmount(*psbta.fee));
1788 6 : }
1789 16 : result.pushKV("next", PSBTRoleName(psbta.next));
1790 16 : if (!psbta.error.empty()) {
1791 8 : result.pushKV("error", psbta.error);
1792 8 : }
1793 :
1794 : return result;
1795 80 : }
1796 :
1797 626 : void RegisterRawTransactionRPCCommands(CRPCTable &t)
1798 : {
1799 : // clang-format off
1800 1179 : static const CRPCCommand commands[] =
1801 553 : { // category name actor (function) argNames
1802 : // --------------------- ------------------------ ----------------------- ----------
1803 553 : { "rawtransactions", "getrawtransaction", &getrawtransaction, {"txid","verbose","blockhash"} },
1804 553 : { "rawtransactions", "createrawtransaction", &createrawtransaction, {"inputs","outputs","locktime","replaceable"} },
1805 553 : { "rawtransactions", "decoderawtransaction", &decoderawtransaction, {"hexstring","iswitness"} },
1806 553 : { "rawtransactions", "decodescript", &decodescript, {"hexstring"} },
1807 553 : { "rawtransactions", "sendrawtransaction", &sendrawtransaction, {"hexstring","maxfeerate"} },
1808 553 : { "rawtransactions", "combinerawtransaction", &combinerawtransaction, {"txs"} },
1809 553 : { "rawtransactions", "signrawtransactionwithkey", &signrawtransactionwithkey, {"hexstring","privkeys","prevtxs","sighashtype"} },
1810 553 : { "rawtransactions", "testmempoolaccept", &testmempoolaccept, {"rawtxs","maxfeerate"} },
1811 553 : { "rawtransactions", "decodepsbt", &decodepsbt, {"psbt"} },
1812 553 : { "rawtransactions", "combinepsbt", &combinepsbt, {"txs"} },
1813 553 : { "rawtransactions", "finalizepsbt", &finalizepsbt, {"psbt", "extract"} },
1814 553 : { "rawtransactions", "createpsbt", &createpsbt, {"inputs","outputs","locktime","replaceable"} },
1815 553 : { "rawtransactions", "converttopsbt", &converttopsbt, {"hexstring","permitsigdata","iswitness"} },
1816 553 : { "rawtransactions", "utxoupdatepsbt", &utxoupdatepsbt, {"psbt", "descriptors"} },
1817 553 : { "rawtransactions", "joinpsbts", &joinpsbts, {"txs"} },
1818 553 : { "rawtransactions", "analyzepsbt", &analyzepsbt, {"psbt"} },
1819 :
1820 553 : { "blockchain", "gettxoutproof", &gettxoutproof, {"txids", "blockhash"} },
1821 553 : { "blockchain", "verifytxoutproof", &verifytxoutproof, {"proof"} },
1822 : };
1823 : // clang-format on
1824 11894 : for (const auto& c : commands) {
1825 11268 : t.appendCommand(c.name, &c);
1826 : }
1827 10580 : }
|