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