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