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