LCOV - code coverage report
Current view: top level - src/rpc - rawtransaction.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 1270 1350 94.1 %
Date: 2026-06-25 07:23:43 Functions: 51 52 98.1 %

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

Generated by: LCOV version 1.16