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