LCOV - code coverage report
Current view: top level - src/rpc - mempool.cpp (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 97.7 % 1064 1040
Test Date: 2026-09-25 06:51:09 Functions: 100.0 % 45 45
Branches: 51.7 % 3688 1906

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2010 Satoshi Nakamoto
       2                 :             : // Copyright (c) 2009-present The Bitcoin Core developers
       3                 :             : // Distributed under the MIT software license, see the accompanying
       4                 :             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5                 :             : 
       6                 :             : #include <rpc/mempool.h>
       7                 :             : #include <rpc/register.h> // IWYU pragma: associated
       8                 :             : 
       9                 :             : #include <common/args.h>
      10                 :             : #include <consensus/amount.h>
      11                 :             : #include <consensus/validation.h>
      12                 :             : #include <core_io.h>
      13                 :             : #include <index/txospenderindex.h>
      14                 :             : #include <net.h>
      15                 :             : #include <net_processing.h>
      16                 :             : #include <netaddress.h>
      17                 :             : #include <netbase.h>
      18                 :             : #include <node/mempool_persist.h>
      19                 :             : #include <node/mempool_persist_args.h>
      20                 :             : #include <node/transaction.h>
      21                 :             : #include <node/txorphanage.h>
      22                 :             : #include <node/types.h>
      23                 :             : #include <policy/feerate.h>
      24                 :             : #include <policy/packages.h>
      25                 :             : #include <policy/policy.h>
      26                 :             : #include <policy/rbf.h>
      27                 :             : #include <primitives/transaction.h>
      28                 :             : #include <rpc/protocol.h>
      29                 :             : #include <rpc/request.h>
      30                 :             : #include <rpc/server.h>
      31                 :             : #include <rpc/server_util.h>
      32                 :             : #include <rpc/util.h>
      33                 :             : #include <script/script.h>
      34                 :             : #include <sync.h>
      35                 :             : #include <tinyformat.h>
      36                 :             : #include <txgraph.h>
      37                 :             : #include <txmempool.h>
      38                 :             : #include <uint256.h>
      39                 :             : #include <univalue.h>
      40                 :             : #include <util/check.h>
      41                 :             : #include <util/expected.h>
      42                 :             : #include <util/feefrac.h>
      43                 :             : #include <util/fs.h>
      44                 :             : #include <util/moneystr.h>
      45                 :             : #include <util/string.h>
      46                 :             : #include <util/time.h>
      47                 :             : #include <util/vector.h>
      48                 :             : #include <validation.h>
      49                 :             : 
      50                 :             : #include <algorithm>
      51                 :             : #include <cstddef>
      52                 :             : #include <cstdint>
      53                 :             : #include <functional>
      54                 :             : #include <list>
      55                 :             : #include <map>
      56                 :             : #include <memory>
      57                 :             : #include <optional>
      58                 :             : #include <ranges>
      59                 :             : #include <set>
      60                 :             : #include <string>
      61                 :             : #include <string_view>
      62                 :             : #include <tuple>
      63                 :             : #include <utility>
      64                 :             : #include <vector>
      65                 :             : 
      66                 :             : namespace node {
      67                 :             : struct NodeContext;
      68                 :             : } // namespace node
      69                 :             : 
      70                 :             : using node::DumpMempool;
      71                 :             : 
      72                 :             : using node::DEFAULT_MAX_BURN_AMOUNT;
      73                 :             : using node::DEFAULT_MAX_RAW_TX_FEE_RATE;
      74                 :             : using node::MempoolPath;
      75                 :             : using node::NodeContext;
      76                 :             : using node::TransactionError;
      77                 :             : using util::ToString;
      78                 :             : 
      79                 :       38741 : static RPCMethod sendrawtransaction()
      80                 :             : {
      81                 :       38741 :     return RPCMethod{
      82                 :       38741 :         "sendrawtransaction",
      83         [ +  - ]:       77482 :         "Submit a raw transaction (serialized, hex-encoded) to the network.\n"
      84                 :             : 
      85                 :             :         "\nIf -privatebroadcast is disabled, then the transaction will be put into the\n"
      86                 :             :         "local mempool of the node and will be sent unconditionally to all currently\n"
      87                 :             :         "connected peers, so using sendrawtransaction for manual rebroadcast will degrade\n"
      88                 :             :         "privacy by leaking the transaction's origin, as nodes will normally not\n"
      89                 :             :         "rebroadcast non-wallet transactions already in their mempool.\n"
      90                 :             : 
      91                 :             :         "\nIf -privatebroadcast is enabled, then the transaction will be sent via\n"
      92                 :             :         "dedicated, short-lived connections to Tor or I2P peers, or to IPv4/IPv6 peers\n"
      93                 :             :         "via the Tor network. This provides best-effort concealment of the transaction's origin.\n"
      94                 :             :         "Private broadcast is experimental and may change in future releases.\n"
      95                 :             :         "Submission does not itself add the transaction to the local mempool; normal\n"
      96                 :             :         "mempool acceptance and relay apply when it is received back from the network.\n"
      97                 :             :         "The private broadcast queue is bounded: when it is full, this RPC fails and\n"
      98                 :             :         "the transaction is not scheduled until an existing one completes or is\n"
      99                 :             :         "aborted. Use getprivatebroadcastinfo to inspect the queue and abortprivatebroadcast to abort.\n"
     100                 :             : 
     101                 :             :         "\nA specific exception, RPC_TRANSACTION_ALREADY_IN_UTXO_SET, may throw if the transaction cannot be added to the mempool.\n"
     102                 :             : 
     103                 :             :         "\nRelated RPCs: createrawtransaction, signrawtransactionwithkey\n",
     104                 :             :         {
     105   [ +  -  +  - ]:       77482 :             {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex string of the raw transaction"},
     106   [ +  -  +  -  :       77482 :             {"maxfeerate", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK())},
                   +  - ]
     107         [ +  - ]:       77482 :              "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT +
     108                 :       38741 :                  "/kvB.\nFee rates larger than 1BTC/kvB are rejected.\nSet to 0 to accept any fee rate."},
     109   [ +  -  +  -  :       77482 :             {"maxburnamount", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_BURN_AMOUNT)},
                   +  - ]
     110         [ +  - ]:       77482 :              "Reject transactions with provably unspendable outputs (e.g. 'datacarrier' outputs that use the OP_RETURN opcode) greater than the specified value, expressed in " + CURRENCY_UNIT + ".\n"
     111                 :             :              "If burning funds through unspendable outputs is desired, increase this value.\n"
     112                 :       38741 :              "This check is based on heuristics and does not guarantee spendability of outputs.\n"},
     113                 :             :         },
     114         [ +  - ]:       77482 :         RPCResult{
     115   [ +  -  +  - ]:       77482 :             RPCResult::Type::STR_HEX, "", "The transaction hash in hex"
     116         [ +  - ]:       77482 :         },
     117                 :       38741 :         RPCExamples{
     118                 :             :             "\nCreate a transaction\n"
     119   [ +  -  +  -  :       77482 :             + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") +
             +  -  +  - ]
     120                 :       38741 :             "Sign the transaction, and get back the hex\n"
     121   [ +  -  +  -  :      154964 :             + HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
             +  -  +  - ]
     122                 :       38741 :             "\nSend the transaction (signed hex)\n"
     123   [ +  -  +  -  :      154964 :             + HelpExampleCli("sendrawtransaction", "\"signedhex\"") +
             +  -  +  - ]
     124                 :       38741 :             "\nAs a JSON-RPC call\n"
     125   [ +  -  +  -  :      154964 :             + HelpExampleRpc("sendrawtransaction", "\"signedhex\"")
             +  -  +  - ]
     126         [ +  - ]:       38741 :                 },
     127                 :       38741 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
     128                 :             :         {
     129         [ +  + ]:       36204 :             const CAmount max_burn_amount = request.params[2].isNull() ? 0 : AmountFromValue(request.params[2]);
     130                 :             : 
     131                 :       36204 :             CMutableTransaction mtx;
     132   [ +  -  +  -  :       36204 :             if (!DecodeHexTx(mtx, request.params[0].get_str())) {
             +  -  +  + ]
     133   [ +  -  +  - ]:         652 :                 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input.");
     134                 :             :             }
     135                 :             : 
     136         [ +  + ]:      107021 :             for (const auto& out : mtx.vout) {
     137   [ +  +  +  -  :       71147 :                 if((out.scriptPubKey.IsUnspendable() || !out.scriptPubKey.HasValidOps()) && out.nValue > max_burn_amount) {
             +  +  +  + ]
     138   [ +  -  +  - ]:           8 :                     throw JSONRPCTransactionError(TransactionError::MAX_BURN_EXCEEDED);
     139                 :             :                 }
     140                 :             :             }
     141                 :             : 
     142         [ +  - ]:       35874 :             CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
     143                 :             : 
     144   [ +  -  +  - ]:       35874 :             const CFeeRate max_raw_tx_fee_rate{ParseFeeRate(self.Arg<UniValue>("maxfeerate"))};
     145                 :             : 
     146         [ +  - ]:       35874 :             int64_t virtual_size = GetVirtualTransactionSize(*tx);
     147         [ +  - ]:       35874 :             CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size);
     148                 :             : 
     149         [ +  - ]:       35874 :             std::string err_string;
     150                 :       35874 :             AssertLockNotHeld(cs_main);
     151         [ +  - ]:       35874 :             NodeContext& node = EnsureAnyNodeContext(request.context);
     152   [ +  -  +  - ]:       35874 :             const bool private_broadcast_enabled{gArgs.GetBoolArg("-privatebroadcast", DEFAULT_PRIVATE_BROADCAST)};
     153         [ +  + ]:       10020 :             if (private_broadcast_enabled &&
     154   [ +  +  +  -  :       35875 :                 !g_reachable_nets.Contains(NET_ONION) &&
                   -  + ]
     155         [ +  - ]:           1 :                 !g_reachable_nets.Contains(NET_I2P)) {
     156                 :           1 :                 throw JSONRPCError(RPC_MISC_ERROR,
     157         [ +  - ]:           1 :                                    "-privatebroadcast is enabled, but none of the Tor or I2P networks is "
     158                 :             :                                    "reachable. Maybe the location of the Tor proxy couldn't be retrieved "
     159                 :             :                                    "from the Tor daemon at startup. Check whether the Tor daemon is running "
     160         [ +  - ]:           3 :                                    "and that -torcontrol, -torpassword and -i2psam are configured properly.");
     161                 :             :             }
     162         [ +  + ]:       35873 :             const auto method = private_broadcast_enabled ? node::TxBroadcast::NO_MEMPOOL_PRIVATE_BROADCAST
     163                 :             :                                                           : node::TxBroadcast::MEMPOOL_AND_BROADCAST_TO_ALL;
     164   [ +  -  +  -  :       71746 :             const TransactionError err = BroadcastTransaction(node,
                   +  - ]
     165                 :             :                                                               tx,
     166                 :             :                                                               err_string,
     167                 :             :                                                               max_raw_tx_fee,
     168                 :             :                                                               method,
     169                 :             :                                                               /*wait_callback=*/true);
     170         [ +  + ]:       35873 :             if (TransactionError::OK != err) {
     171         [ +  - ]:        4445 :                 throw JSONRPCTransactionError(err, err_string);
     172                 :             :             }
     173                 :             : 
     174   [ +  -  +  - ]:       62856 :             return tx->GetHash().GetHex();
     175   [ +  -  +  - ]:       98730 :         },
     176   [ +  -  +  -  :      271187 :     };
             +  +  -  - ]
     177   [ +  -  +  -  :      232446 : }
             +  -  -  - ]
     178                 :             : 
     179                 :        2549 : static RPCMethod getprivatebroadcastinfo()
     180                 :             : {
     181                 :        2549 :     return RPCMethod{
     182                 :        2549 :         "getprivatebroadcastinfo",
     183         [ +  - ]:        5098 :         "Returns information about transactions tracked for private broadcast.\n"
     184                 :             :         "Transactions that have reached the send-attempt limit remain in the result with attempts_remaining=0.\n"
     185                 :             :         "This method is only available when running with -privatebroadcast enabled.\n",
     186                 :             :         {},
     187         [ +  - ]:        5098 :         RPCResult{
     188         [ +  - ]:        5098 :             RPCResult::Type::OBJ, "", "",
     189                 :             :             {
     190   [ +  -  +  - ]:        5098 :                 {RPCResult::Type::ARR, "transactions", "",
     191                 :             :                     {
     192   [ +  -  +  - ]:        5098 :                         {RPCResult::Type::OBJ, "", "",
     193                 :             :                             {
     194   [ +  -  +  - ]:        5098 :                                 {RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
     195   [ +  -  +  - ]:        5098 :                                 {RPCResult::Type::STR_HEX, "wtxid", "The transaction witness hash in hex"},
     196   [ +  -  +  - ]:        5098 :                                 {RPCResult::Type::STR_HEX, "hex", "The serialized, hex-encoded transaction data"},
     197   [ +  -  +  - ]:        5098 :                                 {RPCResult::Type::NUM_TIME, "time_added", "The time this transaction was added to the private broadcast queue (seconds since epoch)"},
     198   [ +  -  +  - ]:        5098 :                                 {RPCResult::Type::NUM, "attempts_remaining", "The number of additional private broadcast send attempts allowed for this transaction"},
     199   [ +  -  +  - ]:        5098 :                                 {RPCResult::Type::ARR, "peers", "Per-peer send and acknowledgment information for this transaction",
     200                 :             :                                     {
     201   [ +  -  +  - ]:        5098 :                                         {RPCResult::Type::OBJ, "", "",
     202                 :             :                                             {
     203   [ +  -  +  - ]:        5098 :                                                 {RPCResult::Type::STR, "address", "The address of the peer to which the transaction was sent"},
     204   [ +  -  +  - ]:        5098 :                                                 {RPCResult::Type::NUM_TIME, "sent", "The time this transaction was picked for sending to this peer via private broadcast (seconds since epoch)"},
     205   [ +  -  +  - ]:        5098 :                                                 {RPCResult::Type::NUM_TIME, "received", /*optional=*/true, "The time this peer acknowledged reception of the transaction (seconds since epoch)"},
     206                 :             :                                             }},
     207                 :             :                                     }},
     208                 :             :                             }},
     209                 :             :                     }},
     210   [ +  -  +  -  :       76470 :             }},
          +  -  +  -  +  
          -  +  -  +  +  
          +  +  +  +  +  
          +  +  +  -  -  
          -  -  -  -  -  
                -  -  - ]
     211                 :        2549 :         RPCExamples{
     212   [ +  -  +  -  :        5098 :             HelpExampleCli("getprivatebroadcastinfo", "")
                   +  - ]
     213   [ +  -  +  -  :       10196 :             + HelpExampleRpc("getprivatebroadcastinfo", "")
             +  -  +  - ]
     214         [ +  - ]:        2549 :         },
     215                 :        2549 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
     216                 :             :         {
     217                 :          13 :             const NodeContext& node{EnsureAnyNodeContext(request.context)};
     218                 :          13 :             const PeerManager& peerman{EnsurePeerman(node)};
     219         [ +  + ]:          13 :             if (!peerman.GetInfo().private_broadcast) {
     220   [ +  -  +  - ]:           2 :                 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Private broadcast is not enabled. Ensure you're running Bitcoin Core with -privatebroadcast=1.");
     221                 :             :             }
     222                 :             : 
     223                 :          12 :             const auto txs{peerman.GetPrivateBroadcastInfo()};
     224                 :             : 
     225                 :          12 :             UniValue transactions(UniValue::VARR);
     226         [ +  + ]:       50023 :             for (const auto& tx_info : txs) {
     227                 :       50011 :                 UniValue o(UniValue::VOBJ);
     228   [ +  -  +  -  :      100022 :                 o.pushKV("txid", tx_info.tx->GetHash().ToString());
             +  -  +  - ]
     229   [ +  -  +  -  :      100022 :                 o.pushKV("wtxid", tx_info.tx->GetWitnessHash().ToString());
             +  -  +  - ]
     230   [ +  -  +  -  :      100022 :                 o.pushKV("hex", EncodeHexTx(*tx_info.tx));
             +  -  +  - ]
     231   [ +  -  +  -  :      100022 :                 o.pushKV("time_added", TicksSinceEpoch<std::chrono::seconds>(tx_info.time_added));
                   +  - ]
     232   [ +  -  +  -  :      100022 :                 o.pushKV("attempts_remaining", tx_info.attempts_remaining);
                   +  - ]
     233                 :       50011 :                 UniValue peers(UniValue::VARR);
     234         [ +  + ]:       50035 :                 for (const auto& peer : tx_info.peers) {
     235                 :          24 :                     UniValue p(UniValue::VOBJ);
     236   [ +  -  +  -  :          48 :                     p.pushKV("address", peer.address.ToStringAddrPort());
             +  -  +  - ]
     237   [ +  -  +  -  :          48 :                     p.pushKV("sent", TicksSinceEpoch<std::chrono::seconds>(peer.sent));
                   +  - ]
     238         [ +  - ]:          24 :                     if (peer.received.has_value()) {
     239   [ +  -  +  -  :          48 :                         p.pushKV("received", TicksSinceEpoch<std::chrono::seconds>(*peer.received));
                   +  - ]
     240                 :             :                     }
     241         [ +  - ]:          24 :                     peers.push_back(std::move(p));
     242                 :          24 :                 }
     243   [ +  -  +  - ]:      100022 :                 o.pushKV("peers", std::move(peers));
     244         [ +  - ]:       50011 :                 transactions.push_back(std::move(o));
     245                 :       50011 :             }
     246                 :             : 
     247                 :          12 :             UniValue ret(UniValue::VOBJ);
     248   [ +  -  +  - ]:          24 :             ret.pushKV("transactions", std::move(transactions));
     249                 :          12 :             return ret;
     250                 :          12 :         },
     251   [ +  -  +  - ]:       10196 :     };
     252   [ +  -  +  -  :       61176 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             -  -  -  - ]
     253                 :             : 
     254                 :        2540 : static RPCMethod abortprivatebroadcast()
     255                 :             : {
     256                 :        2540 :     return RPCMethod{
     257                 :        2540 :         "abortprivatebroadcast",
     258         [ +  - ]:        5080 :         "Abort private broadcast attempts for a transaction currently being privately broadcast.\n"
     259                 :             :         "The transaction will be removed from the private broadcast queue.\n"
     260                 :             :         "This method is only available when running with -privatebroadcast enabled.\n",
     261                 :             :         {
     262   [ +  -  +  - ]:        5080 :             {"id", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A transaction identifier to abort. It will be matched against both txid and wtxid for all transactions in the private broadcast queue.\n"
     263                 :             :                                                                 "If the provided id matches a txid that corresponds to multiple transactions with different wtxids, multiple transactions will be removed and returned."},
     264                 :             :         },
     265         [ +  - ]:        5080 :         RPCResult{
     266   [ +  -  +  - ]:        5080 :             RPCResult::Type::OBJ, "", "",
     267                 :             :             {
     268   [ +  -  +  - ]:        5080 :                 {RPCResult::Type::ARR, "removed_transactions", "Transactions removed from the private broadcast queue",
     269                 :             :                     {
     270   [ +  -  +  - ]:        5080 :                         {RPCResult::Type::OBJ, "", "",
     271                 :             :                             {
     272   [ +  -  +  - ]:        5080 :                                 {RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
     273   [ +  -  +  - ]:        5080 :                                 {RPCResult::Type::STR_HEX, "wtxid", "The transaction witness hash in hex"},
     274   [ +  -  +  - ]:        5080 :                                 {RPCResult::Type::STR_HEX, "hex", "The serialized, hex-encoded transaction data"},
     275                 :             :                             }},
     276                 :             :                     }},
     277                 :             :             }
     278   [ +  -  +  -  :       35560 :         },
          +  -  +  -  +  
          +  +  +  +  +  
          -  -  -  -  -  
                      - ]
     279                 :        2540 :         RPCExamples{
     280   [ +  -  +  -  :        5080 :             HelpExampleCli("abortprivatebroadcast", "\"id\"")
                   +  - ]
     281   [ +  -  +  -  :       10160 :             + HelpExampleRpc("abortprivatebroadcast", "\"id\"")
             +  -  +  - ]
     282         [ +  - ]:        2540 :         },
     283                 :        2540 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
     284                 :             :         {
     285                 :             : 
     286                 :           4 :             const NodeContext& node{EnsureAnyNodeContext(request.context)};
     287                 :           4 :             PeerManager& peerman{EnsurePeerman(node)};
     288         [ +  + ]:           4 :             if (!peerman.GetInfo().private_broadcast) {
     289   [ +  -  +  - ]:           2 :                 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Private broadcast is not enabled. Ensure you're running Bitcoin Core with -privatebroadcast=1.");
     290                 :             :             }
     291                 :             : 
     292         [ +  - ]:           3 :             const uint256 id{ParseHashV(self.Arg<UniValue>("id"), "id")};
     293                 :             : 
     294                 :           3 :             const auto removed_txs{peerman.AbortPrivateBroadcast(id)};
     295         [ +  + ]:           3 :             if (removed_txs.empty()) {
     296   [ +  -  +  - ]:           2 :                 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in private broadcast queue. Check getprivatebroadcastinfo.");
     297                 :             :             }
     298                 :             : 
     299                 :           2 :             UniValue removed_transactions(UniValue::VARR);
     300         [ +  + ]:           4 :             for (const auto& tx : removed_txs) {
     301                 :           2 :                 UniValue o(UniValue::VOBJ);
     302   [ +  -  +  -  :           4 :                 o.pushKV("txid", tx->GetHash().ToString());
             +  -  +  - ]
     303   [ +  -  +  -  :           4 :                 o.pushKV("wtxid", tx->GetWitnessHash().ToString());
             +  -  +  - ]
     304   [ +  -  +  -  :           4 :                 o.pushKV("hex", EncodeHexTx(*tx));
             +  -  +  - ]
     305         [ +  - ]:           2 :                 removed_transactions.push_back(std::move(o));
     306                 :           2 :             }
     307                 :           2 :             UniValue ret(UniValue::VOBJ);
     308   [ +  -  +  - ]:           4 :             ret.pushKV("removed_transactions", std::move(removed_transactions));
     309                 :           2 :             return ret;
     310                 :           3 :         },
     311   [ +  -  +  -  :       12700 :     };
             +  +  -  - ]
     312   [ +  -  +  -  :       30480 : }
          +  -  +  -  +  
             -  +  -  -  
                      - ]
     313                 :             : 
     314                 :        3977 : static RPCMethod testmempoolaccept()
     315                 :             : {
     316                 :        3977 :     return RPCMethod{
     317                 :        3977 :         "testmempoolaccept",
     318                 :             :         "Returns result of mempool acceptance tests indicating if raw transaction(s) (serialized, hex-encoded) would be accepted by mempool.\n"
     319                 :             :         "\nIf multiple transactions are passed in, parents must come before children and package policies apply: the transactions cannot conflict with any mempool transactions or each other.\n"
     320                 :             :         "\nIf one transaction fails, other transactions may not be fully validated (the 'allowed' key will be blank).\n"
     321   [ +  -  +  - ]:        7954 :         "\nThe maximum number of transactions allowed is " + ToString(MAX_PACKAGE_COUNT) + ".\n"
     322                 :             :         "\nThis checks if transactions violate the consensus or policy rules.\n"
     323                 :        3977 :         "\nSee sendrawtransaction call.\n",
     324                 :             :         {
     325   [ +  -  +  - ]:        7954 :             {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of hex strings of raw transactions.",
     326                 :             :                 {
     327   [ +  -  +  - ]:        7954 :                     {"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
     328                 :             :                 },
     329                 :             :             },
     330   [ +  -  +  -  :        7954 :             {"maxfeerate", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK())},
                   +  - ]
     331         [ +  - ]:        7954 :              "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT +
     332                 :        3977 :                  "/kvB.\nFee rates larger than 1BTC/kvB are rejected.\nSet to 0 to accept any fee rate."},
     333                 :             :         },
     334         [ +  - ]:        7954 :         RPCResult{
     335   [ +  -  +  - ]:        7954 :             RPCResult::Type::ARR, "", "The result of the mempool acceptance test for each raw transaction in the input array.\n"
     336                 :             :                                       "Returns results for each transaction in the same order they were passed in.\n"
     337                 :             :                                       "Transactions that cannot be fully validated due to failures in other transactions will not contain an 'allowed' result.\n",
     338                 :             :             {
     339   [ +  -  +  - ]:        7954 :                 {RPCResult::Type::OBJ, "", "",
     340                 :             :                 {
     341   [ +  -  +  - ]:        7954 :                     {RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
     342   [ +  -  +  - ]:        7954 :                     {RPCResult::Type::STR_HEX, "wtxid", "The transaction witness hash in hex"},
     343   [ +  -  +  - ]:        7954 :                     {RPCResult::Type::STR, "package-error", /*optional=*/true, "Package validation error, if any (only possible if rawtxs had more than 1 transaction)."},
     344   [ +  -  +  - ]:        7954 :                     {RPCResult::Type::BOOL, "allowed", /*optional=*/true, "Whether this tx would be accepted to the mempool and pass client-specified maxfeerate. "
     345                 :             :                                                        "If not present, the tx was not fully validated due to a failure in another tx in the list."},
     346   [ +  -  +  - ]:        7954 :                     {RPCResult::Type::NUM, "vsize_adjusted", /*optional=*/true, "Maximum of sigop-adjusted size (-bytespersigop) and virtual transaction size as defined in BIP 141 (only present when 'allowed' is true)."},
     347   [ +  -  +  - ]:        7954 :                     {RPCResult::Type::NUM, "vsize", /*optional=*/true, "(DEPRECATED) Was previously erroneously described as the BIP 141 vsize, but is actually sigops-adjusted vsize.\n"
     348                 :             :                                                                 "Use vsize_bip141 to actually get that behavior or switch to the explicit vsize_adjusted for retained behavior."},
     349   [ +  -  +  - ]:        7954 :                     {RPCResult::Type::NUM, "vsize_bip141", /*optional=*/true, "Virtual transaction size as defined in BIP 141.\n"
     350                 :             :                                                                        "This is different from actual serialized size for witness transactions as witness data is discounted (only present when 'allowed' is true)."},
     351   [ +  -  +  - ]:        7954 :                     {RPCResult::Type::OBJ, "fees", /*optional=*/true, "Transaction fees (only present if 'allowed' is true)",
     352                 :             :                     {
     353   [ +  -  +  - ]:        7954 :                         {RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT},
     354   [ +  -  +  - ]:        7954 :                         {RPCResult::Type::STR_AMOUNT, "effective-feerate", /*optional=*/false, "the effective feerate in " + CURRENCY_UNIT + " per KvB. May differ from the base feerate if, for example, there are modified fees from prioritisetransaction or a package feerate was used."},
     355   [ +  -  +  - ]:        7954 :                         {RPCResult::Type::ARR, "effective-includes", /*optional=*/false, "transactions whose fees and vsizes are included in effective-feerate.",
     356   [ +  -  +  - ]:        7954 :                             {RPCResult{RPCResult::Type::STR_HEX, "", "transaction wtxid in hex"},
     357                 :             :                         }},
     358                 :             :                     }},
     359   [ +  -  +  - ]:        7954 :                     {RPCResult::Type::STR, "reject-reason", /*optional=*/true, "Rejection reason (only present when 'allowed' is false)"},
     360   [ +  -  +  - ]:        7954 :                     {RPCResult::Type::STR, "reject-details", /*optional=*/true, "Rejection details (only present when 'allowed' is false and rejection details exist)"},
     361                 :             :                 }},
     362                 :             :             }
     363   [ +  -  +  -  :      135218 :         },
          +  -  +  -  +  
          -  +  +  +  +  
          +  +  +  +  -  
          -  -  -  -  -  
                   -  - ]
     364                 :        3977 :         RPCExamples{
     365                 :             :             "\nCreate a transaction\n"
     366   [ +  -  +  -  :        7954 :             + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") +
             +  -  +  - ]
     367                 :        3977 :             "Sign the transaction, and get back the hex\n"
     368   [ +  -  +  -  :       15908 :             + HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
             +  -  +  - ]
     369                 :        3977 :             "\nTest acceptance of the transaction (signed hex)\n"
     370   [ +  -  +  -  :       15908 :             + HelpExampleCli("testmempoolaccept", R"('["signedhex"]')") +
             +  -  +  - ]
     371                 :        3977 :             "\nAs a JSON-RPC call\n"
     372   [ +  -  +  -  :       15908 :             + HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]")
             +  -  +  - ]
     373         [ +  - ]:        3977 :                 },
     374                 :        3977 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
     375                 :             :         {
     376                 :        1440 :             const UniValue raw_transactions = request.params[0].get_array();
     377   [ -  +  +  +  :        1440 :             if (raw_transactions.size() < 1 || raw_transactions.size() > MAX_PACKAGE_COUNT) {
                   +  + ]
     378                 :           2 :                 throw JSONRPCError(RPC_INVALID_PARAMETER,
     379   [ +  -  +  -  :           6 :                                    "Array must contain between 1 and " + ToString(MAX_PACKAGE_COUNT) + " transactions.");
                   +  - ]
     380                 :             :             }
     381                 :             : 
     382   [ +  -  +  + ]:        1438 :             const CFeeRate max_raw_tx_fee_rate{ParseFeeRate(self.Arg<UniValue>("maxfeerate"))};
     383                 :             : 
     384                 :        1436 :             std::vector<CTransactionRef> txns;
     385   [ -  +  +  - ]:        1436 :             txns.reserve(raw_transactions.size());
     386   [ +  -  +  + ]:        3456 :             for (const auto& rawtx : raw_transactions.getValues()) {
     387         [ +  - ]:        2021 :                 CMutableTransaction mtx;
     388   [ +  -  +  -  :        2021 :                 if (!DecodeHexTx(mtx, rawtx.get_str())) {
                   +  + ]
     389                 :           1 :                     throw JSONRPCError(RPC_DESERIALIZATION_ERROR,
     390   [ +  -  +  -  :           3 :                                        "TX decode failed: " + rawtx.get_str() + " Make sure the tx has at least one input.");
                   +  - ]
     391                 :             :                 }
     392   [ +  -  +  - ]:        6060 :                 txns.emplace_back(MakeTransactionRef(std::move(mtx)));
     393                 :        2021 :             }
     394                 :             : 
     395         [ +  - ]:        1435 :             NodeContext& node = EnsureAnyNodeContext(request.context);
     396         [ +  - ]:        1435 :             CTxMemPool& mempool = EnsureMemPool(node);
     397         [ +  - ]:        1435 :             ChainstateManager& chainman = EnsureChainman(node);
     398         [ +  - ]:        1435 :             Chainstate& chainstate = chainman.ActiveChainstate();
     399                 :        2870 :             const PackageMempoolAcceptResult package_result = [&] {
     400                 :        1435 :                 LOCK(::cs_main);
     401   [ -  +  +  +  :        1435 :                 if (txns.size() > 1) return ProcessNewPackage(chainstate, mempool, txns, /*test_accept=*/true, /*client_maxfeerate=*/{});
                   +  - ]
     402         [ +  - ]:        1359 :                 return PackageMempoolAcceptResult(txns[0]->GetWitnessHash(),
     403   [ +  -  +  - ]:        1359 :                                                   chainman.ProcessTransaction(txns[0], /*test_accept=*/true));
     404         [ +  - ]:        2870 :             }();
     405                 :             : 
     406                 :        1435 :             UniValue rpc_result(UniValue::VARR);
     407                 :             :             // We will check transaction fees while we iterate through txns in order. If any transaction fee
     408                 :             :             // exceeds maxfeerate, we will leave the rest of the validation results blank, because it
     409                 :             :             // doesn't make sense to return a validation result for a transaction if its ancestor(s) would
     410                 :             :             // not be submitted.
     411                 :        1435 :             bool exit_early{false};
     412         [ +  + ]:        3455 :             for (const auto& tx : txns) {
     413                 :        2020 :                 UniValue result_inner(UniValue::VOBJ);
     414   [ +  -  +  -  :        4040 :                 result_inner.pushKV("txid", tx->GetHash().GetHex());
             +  -  +  - ]
     415   [ +  -  +  -  :        4040 :                 result_inner.pushKV("wtxid", tx->GetWitnessHash().GetHex());
             +  -  +  - ]
     416         [ +  + ]:        2020 :                 if (package_result.m_state.GetResult() == PackageValidationResult::PCKG_POLICY) {
     417   [ +  -  +  -  :         198 :                     result_inner.pushKV("package-error", package_result.m_state.ToString());
             +  -  +  - ]
     418                 :             :                 }
     419                 :        2020 :                 auto it = package_result.m_tx_results.find(tx->GetWitnessHash());
     420   [ +  +  +  + ]:        2020 :                 if (exit_early || it == package_result.m_tx_results.end()) {
     421                 :             :                     // Validation unfinished. Just return the txid and wtxid.
     422         [ +  - ]:         139 :                     rpc_result.push_back(std::move(result_inner));
     423                 :         139 :                     continue;
     424                 :             :                 }
     425         [ +  - ]:        1881 :                 const auto& tx_result = it->second;
     426                 :             :                 // Package testmempoolaccept doesn't allow transactions to already be in the mempool.
     427         [ +  - ]:        1881 :                 CHECK_NONFATAL(tx_result.m_result_type != MempoolAcceptResult::ResultType::MEMPOOL_ENTRY);
     428         [ +  + ]:        1881 :                 if (tx_result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
     429         [ +  - ]:        1632 :                     const CAmount fee = tx_result.m_base_fees.value();
     430                 :             :                     // Check that fee does not exceed maximum fee
     431         [ +  - ]:        1632 :                     const int64_t virtual_size = tx_result.m_vsize.value();
     432         [ +  - ]:        1632 :                     const CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size);
     433         [ +  + ]:        1632 :                     if (max_raw_tx_fee && fee > max_raw_tx_fee) {
     434   [ +  -  +  -  :           8 :                         result_inner.pushKV("allowed", false);
                   +  - ]
     435   [ +  -  +  -  :           4 :                         result_inner.pushKV("reject-reason", "max-fee-exceeded");
                   +  - ]
     436                 :           4 :                         exit_early = true;
     437                 :             :                     } else {
     438                 :             :                         // Only return the fee and vsize if the transaction would pass ATMP.
     439                 :             :                         // These can be used to calculate the feerate.
     440   [ +  -  +  -  :        3256 :                         result_inner.pushKV("allowed", true);
                   +  - ]
     441   [ +  -  +  -  :        3256 :                         result_inner.pushKV("vsize_adjusted", virtual_size);
                   +  - ]
     442   [ +  -  +  -  :        3256 :                         result_inner.pushKV("vsize", virtual_size);
                   +  - ]
     443   [ +  -  +  -  :        3256 :                         result_inner.pushKV("vsize_bip141", GetVirtualTransactionSize(*tx));
             +  -  +  - ]
     444                 :        1628 :                         UniValue fees(UniValue::VOBJ);
     445   [ +  -  +  -  :        3256 :                         fees.pushKV("base", ValueFromAmount(fee));
                   +  - ]
     446   [ +  -  +  -  :        3256 :                         fees.pushKV("effective-feerate", ValueFromAmount(tx_result.m_effective_feerate.value().GetFeePerK()));
             +  -  +  - ]
     447                 :        1628 :                         UniValue effective_includes_res(UniValue::VARR);
     448   [ +  -  +  + ]:        3256 :                         for (const auto& wtxid : tx_result.m_wtxids_fee_calculations.value()) {
     449   [ +  -  +  -  :        1628 :                             effective_includes_res.push_back(wtxid.ToString());
                   +  - ]
     450                 :             :                         }
     451   [ +  -  +  - ]:        3256 :                         fees.pushKV("effective-includes", std::move(effective_includes_res));
     452   [ +  -  +  - ]:        3256 :                         result_inner.pushKV("fees", std::move(fees));
     453                 :        1628 :                     }
     454                 :             :                 } else {
     455   [ +  -  +  -  :         498 :                     result_inner.pushKV("allowed", false);
                   +  - ]
     456         [ +  - ]:         249 :                     const TxValidationState state = tx_result.m_state;
     457         [ +  + ]:         249 :                     if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
     458   [ +  -  +  -  :         232 :                         result_inner.pushKV("reject-reason", "missing-inputs");
                   +  - ]
     459                 :             :                     } else {
     460   [ -  +  +  -  :         399 :                         result_inner.pushKV("reject-reason", state.GetRejectReason());
             +  -  +  - ]
     461   [ +  -  +  -  :         266 :                         result_inner.pushKV("reject-details", state.ToString());
             +  -  +  - ]
     462                 :             :                     }
     463                 :         249 :                 }
     464         [ +  - ]:        1881 :                 rpc_result.push_back(std::move(result_inner));
     465                 :        2020 :             }
     466                 :        1435 :             return rpc_result;
     467                 :        1441 :         },
     468   [ +  -  +  -  :       35793 :     };
          +  -  +  +  +  
             +  -  -  -  
                      - ]
     469   [ +  -  +  -  :      143172 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  -  -  
                -  -  - ]
     470                 :             : 
     471                 :        3681 : static std::vector<RPCResult> ClusterDescription()
     472                 :             : {
     473                 :        3681 :     return {
     474   [ +  -  +  - ]:        7362 :         RPCResult{RPCResult::Type::NUM, "clusterweight", "total sigops-adjusted weight (as defined in BIP 141 and modified by '-bytespersigop')"},
     475   [ +  -  +  - ]:        7362 :         RPCResult{RPCResult::Type::NUM, "txcount", "number of transactions"},
     476   [ +  -  +  - ]:        7362 :         RPCResult{RPCResult::Type::ARR, "chunks", "chunks in this cluster (in mining order)",
     477   [ +  -  +  - ]:        7362 :             {RPCResult{RPCResult::Type::OBJ, "chunk", "",
     478                 :             :                 {
     479   [ +  -  +  - ]:        7362 :                     RPCResult{RPCResult::Type::STR_AMOUNT, "chunkfee", "fees of the transactions in this chunk"},
     480   [ +  -  +  - ]:        7362 :                     RPCResult{RPCResult::Type::NUM, "chunkweight", "sigops-adjusted weight of all transactions in this chunk"},
     481   [ +  -  +  - ]:        7362 :                     RPCResult{RPCResult::Type::ARR, "txs", "transactions in this chunk in mining order",
     482   [ +  -  +  -  :       18405 :                         {RPCResult{RPCResult::Type::STR_HEX, "txid", "transaction id"}}},
          +  -  +  +  -  
                      - ]
     483                 :             :                 }
     484   [ +  -  +  +  :       18405 :             }}
                   -  - ]
     485   [ +  -  +  +  :       11043 :         }
                   -  - ]
     486   [ +  -  +  +  :       22086 :     };
                   -  - ]
     487   [ +  -  +  -  :       58896 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  -  -  
                      - ]
     488                 :             : 
     489                 :       28961 : static std::vector<RPCResult> MempoolEntryDescription()
     490                 :             : {
     491                 :       28961 :     std::vector<RPCResult> list = {
     492   [ +  -  +  - ]:       57922 :         {RPCResult::Type::NUM, "vsize", "(DEPRECATED) Was previously erroneously described as the BIP 141 vsize, but is actually sigops-adjusted vsize.\n"
     493                 :             :         "Use vsize_bip141 to actually get that behavior or switch to the explicit vsize_adjusted for retained behavior."},
     494   [ +  -  +  - ]:       57922 :         {RPCResult::Type::NUM, "vsize_bip141", "Virtual transaction size as defined in BIP 141.\n"
     495                 :             :         "This is different from actual serialized size for witness transactions as witness data is discounted."},
     496   [ +  -  +  - ]:       57922 :         {RPCResult::Type::NUM, "vsize_adjusted", "Maximum of sigop-adjusted size (-bytespersigop) and virtual transaction size as defined in BIP 141."},
     497   [ +  -  +  - ]:       57922 :         RPCResult{RPCResult::Type::NUM, "weight", "transaction weight as defined in BIP 141."},
     498   [ +  -  +  - ]:       57922 :         RPCResult{RPCResult::Type::NUM_TIME, "time", "local time transaction entered pool in seconds since 1 Jan 1970 GMT"},
     499   [ +  -  +  - ]:       57922 :         RPCResult{RPCResult::Type::NUM, "height", "block height when transaction entered pool"},
     500   [ +  -  +  - ]:       57922 :         RPCResult{RPCResult::Type::NUM, "descendantcount", "number of in-mempool descendant transactions (including this one)"},
     501   [ +  -  +  - ]:       57922 :         RPCResult{RPCResult::Type::NUM, "descendantsize", "virtual transaction size of in-mempool descendants (including this one)"},
     502   [ +  -  +  - ]:       57922 :         RPCResult{RPCResult::Type::NUM, "ancestorcount", "number of in-mempool ancestor transactions (including this one)"},
     503   [ +  -  +  - ]:       57922 :         RPCResult{RPCResult::Type::NUM, "ancestorsize", "virtual transaction size of in-mempool ancestors (including this one)"},
     504   [ +  -  +  - ]:       57922 :         RPCResult{RPCResult::Type::NUM, "chunkweight", "sigops-adjusted weight (as defined in BIP 141 and modified by '-bytespersigop') of this transaction's chunk"},
     505   [ +  -  +  - ]:       57922 :         RPCResult{RPCResult::Type::STR_HEX, "wtxid", "hash of serialized transaction, including witness data"},
     506   [ +  -  +  - ]:       57922 :         RPCResult{RPCResult::Type::OBJ, "fees", "",
     507                 :             :             {
     508   [ +  -  +  - ]:       57922 :                 RPCResult{RPCResult::Type::STR_AMOUNT, "base", "transaction fee, denominated in " + CURRENCY_UNIT},
     509   [ +  -  +  - ]:       57922 :                 RPCResult{RPCResult::Type::STR_AMOUNT, "modified", "transaction fee with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT},
     510   [ +  -  +  - ]:       57922 :                 RPCResult{RPCResult::Type::STR_AMOUNT, "ancestor", "transaction fees of in-mempool ancestors (including this one) with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT},
     511   [ +  -  +  - ]:       57922 :                 RPCResult{RPCResult::Type::STR_AMOUNT, "descendant", "transaction fees of in-mempool descendants (including this one) with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT},
     512   [ +  -  +  - ]:       57922 :                 RPCResult{RPCResult::Type::STR_AMOUNT, "chunk", "transaction fees of chunk, denominated in " + CURRENCY_UNIT},
     513   [ +  -  +  +  :      202727 :             }},
                   -  - ]
     514   [ +  -  +  - ]:       57922 :         RPCResult{RPCResult::Type::ARR, "depends", "unconfirmed transactions used as inputs for this transaction",
     515   [ +  -  +  -  :      144805 :             {RPCResult{RPCResult::Type::STR_HEX, "transactionid", "parent transaction id"}}},
          +  -  +  +  -  
                      - ]
     516   [ +  -  +  - ]:       57922 :         RPCResult{RPCResult::Type::ARR, "spentby", "unconfirmed transactions spending outputs from this transaction",
     517   [ +  -  +  -  :      144805 :             {RPCResult{RPCResult::Type::STR_HEX, "transactionid", "child transaction id"}}},
          +  -  +  +  -  
                      - ]
     518   [ +  -  +  - ]:       57922 :         RPCResult{RPCResult::Type::BOOL, "unbroadcast", "Whether this transaction is currently unbroadcast (initial broadcast not yet acknowledged by any peers)"},
     519   [ +  -  +  +  :      608181 :     };
                   -  - ]
     520   [ +  -  +  -  :       28961 :     if (IsDeprecatedRPCEnabled("bip125")) {
                   +  + ]
     521         [ +  - ]:          68 :         list.emplace_back(RPCResult::Type::BOOL, "bip125-replaceable", "Whether this transaction signals BIP125 replaceability or has an unconfirmed ancestor signaling BIP125 replaceability. (DEPRECATED)\n");
     522                 :             :     }
     523                 :       28961 :     return list;
     524   [ +  -  +  -  :     1332206 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  -  -  
                      - ]
     525                 :             : 
     526                 :       25890 : void AppendChunkInfo(UniValue& all_chunks, FeePerWeight chunk_feerate, std::vector<const CTxMemPoolEntry *> chunk_txs)
     527                 :             : {
     528                 :       25890 :     UniValue chunk(UniValue::VOBJ);
     529   [ +  -  +  -  :       51780 :     chunk.pushKV("chunkfee", ValueFromAmount(chunk_feerate.fee));
                   +  - ]
     530   [ +  -  +  -  :       51780 :     chunk.pushKV("chunkweight", chunk_feerate.size);
                   +  - ]
     531                 :       25890 :     UniValue chunk_txids(UniValue::VARR);
     532         [ +  + ]:       51792 :     for (const auto& chunk_tx : chunk_txs) {
     533   [ +  -  +  -  :       25902 :         chunk_txids.push_back(chunk_tx->GetTx().GetHash().ToString());
                   +  - ]
     534                 :             :     }
     535   [ +  -  +  - ]:       51780 :     chunk.pushKV("txs", std::move(chunk_txids));
     536         [ +  - ]:       25890 :     all_chunks.push_back(std::move(chunk));
     537                 :       25890 : }
     538                 :             : 
     539                 :        1144 : static void clusterToJSON(const CTxMemPool& pool, UniValue& info, std::vector<const CTxMemPoolEntry *> cluster) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
     540                 :             : {
     541                 :        1144 :     AssertLockHeld(pool.cs);
     542                 :        1144 :     int total_weight{0};
     543         [ +  + ]:       27046 :     for (const auto& tx : cluster) {
     544                 :       25902 :         total_weight += tx->GetAdjustedWeight();
     545                 :             :     }
     546   [ +  -  +  - ]:        2288 :     info.pushKV("clusterweight", total_weight);
     547   [ -  +  +  -  :        2288 :     info.pushKV("txcount", cluster.size());
                   +  - ]
     548                 :             : 
     549                 :             :     // Output the cluster by chunk. This isn't handed to us by the mempool, but
     550                 :             :     // we can calculate it by looking at the chunk feerates of each transaction
     551                 :             :     // in the cluster.
     552                 :        1144 :     FeePerWeight current_chunk_feerate = pool.GetMainChunkFeerate(*cluster[0]);
     553                 :        1144 :     std::vector<const CTxMemPoolEntry *> current_chunk;
     554   [ -  +  +  - ]:        1144 :     current_chunk.reserve(cluster.size());
     555                 :             : 
     556                 :        1144 :     UniValue all_chunks(UniValue::VARR);
     557         [ +  + ]:       27046 :     for (const auto& tx : cluster) {
     558         [ +  + ]:       25902 :         if (current_chunk_feerate.size == 0) {
     559                 :             :             // We've iterated all the transactions in the previous chunk; so
     560                 :             :             // append it to the output.
     561   [ +  -  +  - ]:       24746 :             AppendChunkInfo(all_chunks, pool.GetMainChunkFeerate(*current_chunk[0]), current_chunk);
     562         [ +  - ]:       24746 :             current_chunk.clear();
     563                 :       24746 :             current_chunk_feerate = pool.GetMainChunkFeerate(*tx);
     564                 :             :         }
     565         [ +  - ]:       25902 :         current_chunk.push_back(tx);
     566         [ +  - ]:       25902 :         current_chunk_feerate.size -= tx->GetAdjustedWeight();
     567                 :             :     }
     568   [ +  -  +  - ]:        1144 :     AppendChunkInfo(all_chunks, pool.GetMainChunkFeerate(*current_chunk[0]), current_chunk);
     569         [ +  - ]:        1144 :     current_chunk.clear();
     570   [ +  -  +  - ]:        2288 :     info.pushKV("chunks", std::move(all_chunks));
     571                 :        1144 : }
     572                 :             : 
     573                 :        8824 : static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPoolEntry& e) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
     574                 :             : {
     575                 :        8824 :     AssertLockHeld(pool.cs);
     576                 :             : 
     577                 :        8824 :     auto [ancestor_count, ancestor_size, ancestor_fees] = pool.CalculateAncestorData(e);
     578                 :        8824 :     auto [descendant_count, descendant_size, descendant_fees] = pool.CalculateDescendantData(e);
     579                 :             : 
     580   [ +  -  +  - ]:       17648 :     info.pushKV("vsize_adjusted", e.GetTxSize());
     581   [ +  -  +  - ]:       17648 :     info.pushKV("vsize", e.GetTxSize());
     582   [ +  -  +  - ]:       17648 :     info.pushKV("vsize_bip141", GetVirtualTransactionSize(e.GetTx()));
     583   [ +  -  +  - ]:       17648 :     info.pushKV("weight", e.GetTxWeight());
     584   [ +  -  +  - ]:       17648 :     info.pushKV("time", count_seconds(e.GetTime()));
     585   [ +  -  +  - ]:       17648 :     info.pushKV("height", e.GetHeight());
     586   [ +  -  +  - ]:       17648 :     info.pushKV("descendantcount", descendant_count);
     587   [ +  -  +  - ]:       17648 :     info.pushKV("descendantsize", descendant_size);
     588   [ +  -  +  - ]:       17648 :     info.pushKV("ancestorcount", ancestor_count);
     589   [ +  -  +  - ]:       17648 :     info.pushKV("ancestorsize", ancestor_size);
     590   [ +  -  +  -  :       17648 :     info.pushKV("wtxid", e.GetTx().GetWitnessHash().ToString());
                   +  - ]
     591                 :        8824 :     auto feerate = pool.GetMainChunkFeerate(e);
     592   [ +  -  +  - ]:       17648 :     info.pushKV("chunkweight", feerate.size);
     593                 :             : 
     594                 :        8824 :     UniValue fees(UniValue::VOBJ);
     595   [ +  -  +  -  :       17648 :     fees.pushKV("base", ValueFromAmount(e.GetFee()));
                   +  - ]
     596   [ +  -  +  -  :       17648 :     fees.pushKV("modified", ValueFromAmount(e.GetModifiedFee()));
                   +  - ]
     597   [ +  -  +  -  :       17648 :     fees.pushKV("ancestor", ValueFromAmount(ancestor_fees));
                   +  - ]
     598   [ +  -  +  -  :       17648 :     fees.pushKV("descendant", ValueFromAmount(descendant_fees));
                   +  - ]
     599   [ +  -  +  -  :       17648 :     fees.pushKV("chunk", ValueFromAmount(feerate.fee));
                   +  - ]
     600   [ +  -  +  - ]:       17648 :     info.pushKV("fees", std::move(fees));
     601                 :             : 
     602                 :        8824 :     const CTransaction& tx = e.GetTx();
     603                 :        8824 :     std::set<std::string> setDepends;
     604         [ +  + ]:       20910 :     for (const CTxIn& txin : tx.vin)
     605                 :             :     {
     606   [ +  -  +  + ]:       12086 :         if (pool.exists(txin.prevout.hash))
     607   [ +  -  +  - ]:       14680 :             setDepends.insert(txin.prevout.hash.ToString());
     608                 :             :     }
     609                 :             : 
     610                 :        8824 :     UniValue depends(UniValue::VARR);
     611         [ +  + ]:       16164 :     for (const std::string& dep : setDepends)
     612                 :             :     {
     613   [ +  -  +  - ]:        7340 :         depends.push_back(dep);
     614                 :             :     }
     615                 :             : 
     616   [ +  -  +  - ]:       17648 :     info.pushKV("depends", std::move(depends));
     617                 :             : 
     618                 :        8824 :     UniValue spent(UniValue::VARR);
     619   [ +  -  +  -  :       16179 :     for (const CTxMemPoolEntry& child : pool.GetChildren(e)) {
                   +  + ]
     620   [ +  -  +  -  :        7355 :         spent.push_back(child.GetTx().GetHash().ToString());
                   +  - ]
     621                 :           0 :     }
     622                 :             : 
     623   [ +  -  +  - ]:       17648 :     info.pushKV("spentby", std::move(spent));
     624   [ +  -  +  -  :       17648 :     info.pushKV("unbroadcast", pool.IsUnbroadcastTx(tx.GetHash()));
                   +  - ]
     625                 :             : 
     626                 :             :     // Add opt-in RBF status
     627   [ +  -  +  -  :        8824 :     if (IsDeprecatedRPCEnabled("bip125")) {
                   +  + ]
     628                 :           1 :         bool rbfStatus = false;
     629         [ +  - ]:           1 :         RBFTransactionState rbfState = IsRBFOptIn(tx, pool);
     630         [ -  + ]:           1 :         if (rbfState == RBFTransactionState::UNKNOWN) {
     631   [ #  #  #  # ]:           0 :             throw JSONRPCError(RPC_MISC_ERROR, "Transaction is not in mempool");
     632         [ -  + ]:           1 :         } else if (rbfState == RBFTransactionState::REPLACEABLE_BIP125) {
     633                 :           0 :             rbfStatus = true;
     634                 :             :         }
     635   [ +  -  +  -  :           2 :         info.pushKV("bip125-replaceable", rbfStatus);
                   +  - ]
     636                 :             :     }
     637                 :        8824 : }
     638                 :             : 
     639                 :        7857 : UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose, bool include_mempool_sequence)
     640                 :             : {
     641         [ +  + ]:        7857 :     if (verbose) {
     642         [ +  + ]:        1083 :         if (include_mempool_sequence) {
     643   [ +  -  +  - ]:           2 :             throw JSONRPCError(RPC_INVALID_PARAMETER, "Verbose results cannot contain mempool sequence values.");
     644                 :             :         }
     645                 :        1082 :         LOCK(pool.cs);
     646                 :        1082 :         UniValue o(UniValue::VOBJ);
     647   [ +  -  +  + ]:        4939 :         for (const CTxMemPoolEntry& e : pool.entryAll()) {
     648                 :        3857 :             UniValue info(UniValue::VOBJ);
     649         [ +  - ]:        3857 :             entryToJSON(pool, info, e);
     650                 :             :             // Mempool has unique entries so there is no advantage in using
     651                 :             :             // UniValue::pushKV, which checks if the key already exists in O(N).
     652                 :             :             // UniValue::pushKVEnd is used instead which currently is O(1).
     653   [ +  -  +  - ]:        7714 :             o.pushKVEnd(e.GetTx().GetHash().ToString(), std::move(info));
     654                 :        3857 :         }
     655         [ +  - ]:        1082 :         return o;
     656                 :        1082 :     } else {
     657                 :        6774 :         UniValue a(UniValue::VARR);
     658                 :        6774 :         uint64_t mempool_sequence;
     659                 :        6774 :         {
     660         [ +  - ]:        6774 :             LOCK(pool.cs);
     661   [ +  -  +  -  :      255788 :             for (const CTxMemPoolEntry& e : pool.entryAll()) {
                   +  + ]
     662   [ +  -  +  -  :      249014 :                 a.push_back(e.GetTx().GetHash().ToString());
                   +  - ]
     663                 :             :             }
     664         [ +  - ]:        6774 :             mempool_sequence = pool.GetSequence();
     665                 :           0 :         }
     666         [ +  + ]:        6774 :         if (!include_mempool_sequence) {
     667                 :        6753 :             return a;
     668                 :             :         } else {
     669                 :          21 :             UniValue o(UniValue::VOBJ);
     670   [ +  -  +  - ]:          42 :             o.pushKV("txids", std::move(a));
     671   [ +  -  +  -  :          42 :             o.pushKV("mempool_sequence", mempool_sequence);
                   +  - ]
     672                 :          21 :             return o;
     673                 :          21 :         }
     674                 :        6774 :     }
     675                 :             : }
     676                 :             : 
     677                 :        2530 : static RPCMethod getmempoolfeeratediagram()
     678                 :             : {
     679                 :        2530 :     return RPCMethod{"getmempoolfeeratediagram",
     680         [ +  - ]:        5060 :         "Returns the feerate diagram for the whole mempool.",
     681                 :             :         {},
     682                 :             :         {
     683                 :           0 :             RPCResult{"mempool chunks",
     684   [ +  -  +  - ]:        5060 :                 RPCResult::Type::ARR, "", "",
     685                 :             :                 {
     686                 :             :                     {
     687   [ +  -  +  - ]:        5060 :                         RPCResult::Type::OBJ, "", "",
     688                 :             :                         {
     689   [ +  -  +  - ]:        5060 :                             {RPCResult::Type::NUM, "weight", "cumulative sigops-adjusted weight"},
     690   [ +  -  +  - ]:        5060 :                             {RPCResult::Type::STR_AMOUNT, "fee", "cumulative fee"}
     691                 :             :                         }
     692                 :             :                     }
     693                 :             :                 }
     694   [ +  -  +  -  :       22770 :             }
          +  +  +  +  -  
                -  -  - ]
     695                 :             :         },
     696                 :        2530 :         RPCExamples{
     697   [ +  -  +  -  :        5060 :             HelpExampleCli("getmempoolfeeratediagram", "")
                   +  - ]
     698   [ +  -  +  -  :       10120 :             + HelpExampleRpc("getmempoolfeeratediagram", "")
                   +  - ]
     699         [ +  - ]:        2530 :         },
     700                 :        2530 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
     701                 :             :         {
     702                 :           5 :             const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
     703                 :           5 :             LOCK(mempool.cs);
     704                 :             : 
     705                 :           5 :             UniValue result(UniValue::VARR);
     706                 :             : 
     707         [ +  - ]:           5 :             auto diagram = mempool.GetFeerateDiagram();
     708                 :             : 
     709         [ +  + ]:         136 :             for (auto f : diagram) {
     710                 :         131 :                 UniValue o(UniValue::VOBJ);
     711   [ +  -  +  -  :         262 :                 o.pushKV("weight", f.size);
                   +  - ]
     712   [ +  -  +  -  :         262 :                 o.pushKV("fee", ValueFromAmount(f.fee));
                   +  - ]
     713   [ +  -  +  - ]:         131 :                 result.push_back(o);
     714                 :         131 :             }
     715                 :           5 :             return result;
     716         [ +  - ]:          10 :         }
     717   [ +  -  +  -  :       20240 :     };
          +  -  +  -  +  
                +  -  - ]
     718   [ +  -  +  -  :       20240 : }
          +  -  +  -  -  
                      - ]
     719                 :             : 
     720                 :       10388 : static RPCMethod getrawmempool()
     721                 :             : {
     722                 :       10388 :     return RPCMethod{
     723                 :       10388 :         "getrawmempool",
     724         [ +  - ]:       20776 :         "Returns all transaction ids in memory pool as a json array of string transaction ids.\n"
     725                 :             :         "\nHint: use getmempoolentry to fetch a specific transaction from the mempool.\n",
     726                 :             :         {
     727   [ +  -  +  -  :       31164 :             {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "True for a json object, false for array of transaction ids"},
                   +  - ]
     728   [ +  -  +  -  :       31164 :             {"mempool_sequence", RPCArg::Type::BOOL, RPCArg::Default{false}, "If verbose=false, returns a json object with transaction list and mempool sequence number attached."},
                   +  - ]
     729                 :             :         },
     730                 :             :         {
     731         [ +  - ]:       10388 :             RPCResult{"for verbose = false",
     732   [ +  -  +  - ]:       20776 :                 RPCResult::Type::ARR, "", "",
     733                 :             :                 {
     734   [ +  -  +  - ]:       20776 :                     {RPCResult::Type::STR_HEX, "", "The transaction id"},
     735   [ +  -  +  +  :       41552 :                 }},
                   -  - ]
     736         [ +  - ]:       20776 :             RPCResult{"for verbose = true",
     737   [ +  -  +  - ]:       20776 :                 RPCResult::Type::OBJ_DYN, "", "",
     738                 :             :                 {
     739   [ +  -  +  -  :       20776 :                     {RPCResult::Type::OBJ, "transactionid", "", MempoolEntryDescription()},
                   +  - ]
     740   [ +  -  +  +  :       31164 :                 }},
                   -  - ]
     741         [ +  - ]:       20776 :             RPCResult{"for verbose = false and mempool_sequence = true",
     742   [ +  -  +  - ]:       20776 :                 RPCResult::Type::OBJ, "", "",
     743                 :             :                 {
     744   [ +  -  +  - ]:       20776 :                     {RPCResult::Type::ARR, "txids", "",
     745                 :             :                     {
     746   [ +  -  +  - ]:       20776 :                         {RPCResult::Type::STR_HEX, "", "The transaction id"},
     747                 :             :                     }},
     748   [ +  -  +  - ]:       20776 :                     {RPCResult::Type::NUM, "mempool_sequence", "The mempool sequence value."},
     749   [ +  -  +  -  :       93492 :                 }},
          +  +  +  +  -  
                -  -  - ]
     750                 :             :         },
     751                 :       10388 :         RPCExamples{
     752   [ +  -  +  -  :       20776 :             HelpExampleCli("getrawmempool", "true")
                   +  - ]
     753   [ +  -  +  -  :       41552 :             + HelpExampleRpc("getrawmempool", "true")
                   +  - ]
     754         [ +  - ]:       10388 :         },
     755                 :       10388 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
     756                 :             : {
     757                 :        7852 :     bool fVerbose = false;
     758         [ +  + ]:        7852 :     if (!request.params[0].isNull())
     759                 :        1139 :         fVerbose = request.params[0].get_bool();
     760                 :             : 
     761                 :        7852 :     bool include_mempool_sequence = false;
     762         [ +  + ]:        7852 :     if (!request.params[1].isNull()) {
     763                 :          22 :         include_mempool_sequence = request.params[1].get_bool();
     764                 :             :     }
     765                 :             : 
     766                 :        7852 :     return MempoolToJSON(EnsureAnyMemPool(request.context), fVerbose, include_mempool_sequence);
     767                 :             : },
     768   [ +  -  +  -  :      124656 :     };
          +  -  +  -  +  
          +  +  +  -  -  
                   -  - ]
     769   [ +  -  +  -  :      207760 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  -  -  -  -  
                   -  - ]
     770                 :             : 
     771                 :        3149 : static RPCMethod getmempoolancestors()
     772                 :             : {
     773                 :        3149 :     return RPCMethod{
     774                 :        3149 :         "getmempoolancestors",
     775         [ +  - ]:        6298 :         "If txid is in the mempool, returns all in-mempool ancestors.\n",
     776                 :             :         {
     777   [ +  -  +  - ]:        6298 :             {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"},
     778   [ +  -  +  -  :        9447 :             {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "True for a json object, false for array of transaction ids"},
                   +  - ]
     779                 :             :         },
     780                 :             :         {
     781         [ +  - ]:        3149 :             RPCResult{"for verbose = false",
     782   [ +  -  +  - ]:        6298 :                 RPCResult::Type::ARR, "", "",
     783   [ +  -  +  -  :       15745 :                 {{RPCResult::Type::STR_HEX, "", "The transaction id of an in-mempool ancestor transaction"}}},
          +  -  +  +  -  
                      - ]
     784         [ +  - ]:        6298 :             RPCResult{"for verbose = true",
     785   [ +  -  +  - ]:        6298 :                 RPCResult::Type::OBJ_DYN, "", "",
     786                 :             :                 {
     787   [ +  -  +  -  :        6298 :                     {RPCResult::Type::OBJ, "transactionid", "", MempoolEntryDescription()},
                   +  - ]
     788   [ +  -  +  +  :        9447 :                 }},
                   -  - ]
     789                 :             :         },
     790                 :        3149 :         RPCExamples{
     791   [ +  -  +  -  :        6298 :             HelpExampleCli("getmempoolancestors", "\"mytxid\"")
                   +  - ]
     792   [ +  -  +  -  :       12596 :             + HelpExampleRpc("getmempoolancestors", "\"mytxid\"")
                   +  - ]
     793         [ +  - ]:        3149 :         },
     794                 :        3149 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
     795                 :             : {
     796                 :         613 :     bool fVerbose = false;
     797         [ +  + ]:         613 :     if (!request.params[1].isNull())
     798                 :          65 :         fVerbose = request.params[1].get_bool();
     799                 :             : 
     800                 :         613 :     auto txid{Txid::FromUint256(ParseHashV(request.params[0], "txid"))};
     801                 :             : 
     802                 :         613 :     const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
     803                 :         613 :     LOCK(mempool.cs);
     804                 :             : 
     805         [ +  - ]:         613 :     const auto entry{mempool.GetEntry(txid)};
     806         [ -  + ]:         613 :     if (entry == nullptr) {
     807   [ #  #  #  # ]:           0 :         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool");
     808                 :             :     }
     809                 :             : 
     810         [ +  - ]:         613 :     auto ancestors{mempool.CalculateMemPoolAncestors(*entry)};
     811                 :             : 
     812         [ +  + ]:         613 :     if (!fVerbose) {
     813                 :         548 :         UniValue o(UniValue::VARR);
     814         [ +  + ]:       11954 :         for (CTxMemPool::txiter ancestorIt : ancestors) {
     815   [ +  -  +  -  :       11406 :             o.push_back(ancestorIt->GetTx().GetHash().ToString());
                   +  - ]
     816                 :             :         }
     817                 :             :         return o;
     818                 :           0 :     } else {
     819                 :          65 :         UniValue o(UniValue::VOBJ);
     820         [ +  + ]:        2144 :         for (CTxMemPool::txiter ancestorIt : ancestors) {
     821                 :        2079 :             const CTxMemPoolEntry &e = *ancestorIt;
     822                 :        2079 :             UniValue info(UniValue::VOBJ);
     823         [ +  - ]:        2079 :             entryToJSON(mempool, info, e);
     824   [ +  -  +  - ]:        4158 :             o.pushKVEnd(e.GetTx().GetHash().ToString(), std::move(info));
     825                 :        2079 :         }
     826                 :          65 :         return o;
     827                 :          65 :     }
     828         [ +  - ]:        1226 : },
     829   [ +  -  +  -  :       34639 :     };
          +  -  +  -  +  
          +  +  +  -  -  
                   -  - ]
     830   [ +  -  +  -  :       37788 : }
          +  -  +  -  +  
          -  +  -  -  -  
                   -  - ]
     831                 :             : 
     832                 :       12055 : static RPCMethod getmempooldescendants()
     833                 :             : {
     834                 :       12055 :     return RPCMethod{
     835                 :       12055 :         "getmempooldescendants",
     836         [ +  - ]:       24110 :         "If txid is in the mempool, returns all in-mempool descendants.\n",
     837                 :             :         {
     838   [ +  -  +  - ]:       24110 :             {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"},
     839   [ +  -  +  -  :       36165 :             {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "True for a json object, false for array of transaction ids"},
                   +  - ]
     840                 :             :         },
     841                 :             :         {
     842         [ +  - ]:       12055 :             RPCResult{"for verbose = false",
     843   [ +  -  +  - ]:       24110 :                 RPCResult::Type::ARR, "", "",
     844   [ +  -  +  -  :       60275 :                 {{RPCResult::Type::STR_HEX, "", "The transaction id of an in-mempool descendant transaction"}}},
          +  -  +  +  -  
                      - ]
     845         [ +  - ]:       24110 :             RPCResult{"for verbose = true",
     846   [ +  -  +  - ]:       24110 :                 RPCResult::Type::OBJ_DYN, "", "",
     847                 :             :                 {
     848   [ +  -  +  -  :       24110 :                     {RPCResult::Type::OBJ, "transactionid", "", MempoolEntryDescription()},
                   +  - ]
     849   [ +  -  +  +  :       36165 :                 }},
                   -  - ]
     850                 :             :         },
     851                 :       12055 :         RPCExamples{
     852   [ +  -  +  -  :       24110 :             HelpExampleCli("getmempooldescendants", "\"mytxid\"")
                   +  - ]
     853   [ +  -  +  -  :       48220 :             + HelpExampleRpc("getmempooldescendants", "\"mytxid\"")
                   +  - ]
     854         [ +  - ]:       12055 :         },
     855                 :       12055 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
     856                 :             : {
     857                 :        9519 :     bool fVerbose = false;
     858         [ +  + ]:        9519 :     if (!request.params[1].isNull())
     859                 :          65 :         fVerbose = request.params[1].get_bool();
     860                 :             : 
     861                 :        9519 :     auto txid{Txid::FromUint256(ParseHashV(request.params[0], "txid"))};
     862                 :             : 
     863                 :        9519 :     const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
     864                 :        9519 :     LOCK(mempool.cs);
     865                 :             : 
     866         [ +  - ]:        9519 :     const auto it{mempool.GetIter(txid)};
     867         [ -  + ]:        9519 :     if (!it) {
     868   [ #  #  #  # ]:           0 :         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool");
     869                 :             :     }
     870                 :             : 
     871         [ +  - ]:        9519 :     CTxMemPool::setEntries setDescendants;
     872         [ +  - ]:        9519 :     mempool.CalculateDescendants(*it, setDescendants);
     873                 :             :     // CTxMemPool::CalculateDescendants will include the given tx
     874                 :        9519 :     setDescendants.erase(*it);
     875                 :             : 
     876         [ +  + ]:        9519 :     if (!fVerbose) {
     877                 :        9454 :         UniValue o(UniValue::VARR);
     878         [ +  + ]:      175782 :         for (CTxMemPool::txiter descendantIt : setDescendants) {
     879   [ +  -  +  -  :      166328 :             o.push_back(descendantIt->GetTx().GetHash().ToString());
                   +  - ]
     880                 :             :         }
     881                 :             : 
     882                 :             :         return o;
     883                 :           0 :     } else {
     884                 :          65 :         UniValue o(UniValue::VOBJ);
     885         [ +  + ]:        2144 :         for (CTxMemPool::txiter descendantIt : setDescendants) {
     886                 :        2079 :             const CTxMemPoolEntry &e = *descendantIt;
     887                 :        2079 :             UniValue info(UniValue::VOBJ);
     888         [ +  - ]:        2079 :             entryToJSON(mempool, info, e);
     889   [ +  -  +  - ]:        4158 :             o.pushKVEnd(e.GetTx().GetHash().ToString(), std::move(info));
     890                 :        2079 :         }
     891                 :          65 :         return o;
     892                 :          65 :     }
     893         [ +  - ]:       19038 : },
     894   [ +  -  +  -  :      132605 :     };
          +  -  +  -  +  
          +  +  +  -  -  
                   -  - ]
     895   [ +  -  +  -  :      168770 : }
          +  -  +  -  +  
          -  +  -  -  -  
                   -  - ]
     896                 :             : 
     897                 :        3681 : static RPCMethod getmempoolcluster()
     898                 :             : {
     899                 :        3681 :     return RPCMethod{"getmempoolcluster",
     900         [ +  - ]:        7362 :         "Returns mempool data for given cluster\n",
     901                 :             :         {
     902   [ +  -  +  - ]:        7362 :             {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The txid of a transaction in the cluster"},
     903                 :             :         },
     904         [ +  - ]:        7362 :         RPCResult{
     905   [ +  -  +  -  :        7362 :             RPCResult::Type::OBJ, "", "", ClusterDescription()},
             +  -  +  - ]
     906                 :        3681 :         RPCExamples{
     907   [ +  -  +  -  :        7362 :             HelpExampleCli("getmempoolcluster", "txid")
                   +  - ]
     908   [ +  -  +  -  :       14724 :             + HelpExampleRpc("getmempoolcluster", R"("txid")")
             +  -  +  - ]
     909         [ +  - ]:        3681 :         },
     910                 :        3681 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
     911                 :             : {
     912                 :        1145 :     uint256 hash = ParseHashV(request.params[0], "txid");
     913                 :             : 
     914                 :        1145 :     const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
     915                 :        1145 :     LOCK(mempool.cs);
     916                 :             : 
     917         [ +  - ]:        1145 :     auto txid = Txid::FromUint256(hash);
     918         [ +  - ]:        1145 :     const auto entry{mempool.GetEntry(txid)};
     919         [ +  + ]:        1145 :     if (entry == nullptr) {
     920   [ +  -  +  - ]:           2 :         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool");
     921                 :             :     }
     922                 :             : 
     923         [ +  - ]:        1144 :     auto cluster = mempool.GetCluster(txid);
     924                 :             : 
     925                 :        1144 :     UniValue info(UniValue::VOBJ);
     926   [ +  -  +  - ]:        1144 :     clusterToJSON(mempool, info, cluster);
     927                 :        1144 :     return info;
     928         [ +  - ]:        2288 : },
     929   [ +  -  +  -  :       18405 :     };
             +  +  -  - ]
     930         [ +  - ]:        7362 : }
     931                 :             : 
     932                 :        3369 : static RPCMethod getmempoolentry()
     933                 :             : {
     934                 :        3369 :     return RPCMethod{
     935                 :        3369 :         "getmempoolentry",
     936         [ +  - ]:        6738 :         "Returns mempool data for given transaction\n",
     937                 :             :         {
     938   [ +  -  +  - ]:        6738 :             {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"},
     939                 :             :         },
     940         [ +  - ]:        6738 :         RPCResult{
     941   [ +  -  +  -  :        6738 :             RPCResult::Type::OBJ, "", "", MempoolEntryDescription()},
             +  -  +  - ]
     942                 :        3369 :         RPCExamples{
     943   [ +  -  +  -  :        6738 :             HelpExampleCli("getmempoolentry", "\"mytxid\"")
                   +  - ]
     944   [ +  -  +  -  :       13476 :             + HelpExampleRpc("getmempoolentry", "\"mytxid\"")
             +  -  +  - ]
     945         [ +  - ]:        3369 :         },
     946                 :        3369 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
     947                 :             : {
     948                 :         833 :     auto txid{Txid::FromUint256(ParseHashV(request.params[0], "txid"))};
     949                 :             : 
     950                 :         833 :     const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
     951                 :         833 :     LOCK(mempool.cs);
     952                 :             : 
     953         [ +  - ]:         833 :     const auto entry{mempool.GetEntry(txid)};
     954         [ +  + ]:         833 :     if (entry == nullptr) {
     955   [ +  -  +  - ]:          48 :         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool");
     956                 :             :     }
     957                 :             : 
     958                 :         809 :     UniValue info(UniValue::VOBJ);
     959         [ +  - ]:         809 :     entryToJSON(mempool, info, *entry);
     960         [ +  - ]:         809 :     return info;
     961                 :         809 : },
     962   [ +  -  +  -  :       16845 :     };
             +  +  -  - ]
     963         [ +  - ]:        6738 : }
     964                 :             : 
     965                 :        2628 : static RPCMethod gettxspendingprevout()
     966                 :             : {
     967                 :        2628 :     return RPCMethod{"gettxspendingprevout",
     968         [ +  - ]:        5256 :         "Scans the mempool (and the txospenderindex, if available) to find transactions spending any of the given outputs",
     969                 :             :         {
     970   [ +  -  +  - ]:        5256 :             {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The transaction outputs that we want to check, and within each, the txid (string) vout (numeric).",
     971                 :             :                 {
     972   [ +  -  +  - ]:        5256 :                     {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
     973                 :             :                         {
     974   [ +  -  +  - ]:        5256 :                             {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
     975   [ +  -  +  - ]:        5256 :                             {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
     976                 :             :                         },
     977                 :             :                     },
     978                 :             :                 },
     979                 :             :             },
     980   [ +  -  +  - ]:        5256 :             {"options", RPCArg::Type::OBJ_NAMED_PARAMS, RPCArg::Optional::OMITTED, "",
     981                 :             :                 {
     982   [ +  -  +  -  :        7884 :                     {"mempool_only", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true if txospenderindex unavailable, otherwise false"}, "If false and mempool lacks a relevant spend, use txospenderindex (throws an exception if not available)."},
                   +  - ]
     983   [ +  -  +  -  :        7884 :                     {"return_spending_tx", RPCArg::Type::BOOL, RPCArg::DefaultHint{"false"}, "If true, return the full spending tx."},
                   +  - ]
     984                 :             :                 },
     985                 :             :             },
     986                 :             :         },
     987         [ +  - ]:        5256 :         RPCResult{
     988   [ +  -  +  - ]:        5256 :             RPCResult::Type::ARR, "", "",
     989                 :             :             {
     990   [ +  -  +  - ]:        5256 :                 {RPCResult::Type::OBJ, "", "",
     991                 :             :                 {
     992   [ +  -  +  - ]:        5256 :                     {RPCResult::Type::STR_HEX, "txid", "the transaction id of the checked output"},
     993   [ +  -  +  - ]:        5256 :                     {RPCResult::Type::NUM, "vout", "the vout value of the checked output"},
     994   [ +  -  +  - ]:        5256 :                     {RPCResult::Type::STR_HEX, "spendingtxid", /*optional=*/true, "the transaction id of the mempool transaction spending this output (omitted if unspent)"},
     995   [ +  -  +  - ]:        5256 :                     {RPCResult::Type::STR_HEX, "spendingtx", /*optional=*/true, "the transaction spending this output (only if return_spending_tx is set, omitted if unspent)"},
     996   [ +  -  +  - ]:        5256 :                     {RPCResult::Type::STR_HEX, "blockhash", /*optional=*/true, "the hash of the spending block (omitted if unspent or the spending tx is not confirmed)"},
     997                 :             :                 }},
     998                 :             :             }
     999   [ +  -  +  -  :       39420 :         },
          +  -  +  +  +  
             +  -  -  -  
                      - ]
    1000                 :        2628 :         RPCExamples{
    1001   [ +  -  +  -  :        5256 :             HelpExampleCli("gettxspendingprevout", "\"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":3}]\"")
                   +  - ]
    1002   [ +  -  +  -  :       10512 :             + HelpExampleRpc("gettxspendingprevout", "\"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":3}]\"")
             +  -  +  - ]
    1003   [ +  -  +  -  :       15768 :             + HelpExampleCliNamed("gettxspendingprevout", {{"outputs", "[{\"txid\":\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\",\"vout\":3}]"}, {"return_spending_tx", true}})
          +  -  +  -  +  
                +  -  - ]
    1004         [ +  - ]:        2628 :         },
    1005                 :        2628 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
    1006                 :             :         {
    1007                 :          92 :             const UniValue& output_params = request.params[0].get_array();
    1008   [ -  +  +  + ]:          92 :             if (output_params.empty()) {
    1009   [ +  -  +  - ]:           2 :                 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, outputs are missing");
    1010                 :             :             }
    1011         [ +  + ]:          91 :             const UniValue options{request.params[1].isNull() ? UniValue::VOBJ : request.params[1]};
    1012   [ +  -  +  +  :         364 :             RPCTypeCheckObj(options,
                   -  - ]
    1013                 :             :                             {
    1014         [ +  - ]:          91 :                                 {"mempool_only", UniValueType(UniValue::VBOOL)},
    1015         [ +  - ]:          91 :                                 {"return_spending_tx", UniValueType(UniValue::VBOOL)},
    1016                 :             :                             }, /*fAllowNull=*/true, /*fStrict=*/true);
    1017                 :             : 
    1018   [ +  -  +  +  :         184 :             const bool mempool_only{options.exists("mempool_only") ? options["mempool_only"].get_bool() : !g_txospenderindex};
          +  -  +  -  +  
                      - ]
    1019   [ +  -  +  +  :         194 :             const bool return_spending_tx{options.exists("return_spending_tx") ? options["return_spending_tx"].get_bool() : false};
          +  -  +  -  +  
                      - ]
    1020                 :             : 
    1021                 :             :             // Worklist of outpoints to resolve
    1022                 :          91 :             struct Entry {
    1023                 :             :                 COutPoint outpoint;
    1024                 :             :                 size_t request_index;
    1025                 :             :             };
    1026                 :          91 :             std::vector<Entry> prevouts_to_process;
    1027   [ -  +  +  - ]:          91 :             prevouts_to_process.reserve(output_params.size());
    1028   [ -  +  +  + ]:         187 :             for (const size_t idx : std::views::iota(size_t{0}, output_params.size())) {
    1029   [ +  -  +  - ]:         101 :                 const UniValue& o = output_params[idx].get_obj();
    1030                 :             : 
    1031   [ +  +  +  +  :         408 :                 RPCTypeCheckObj(o,
                   +  + ]
    1032                 :             :                                 {
    1033         [ +  - ]:         101 :                                     {"txid", UniValueType(UniValue::VSTR)},
    1034         [ +  - ]:         101 :                                     {"vout", UniValueType(UniValue::VNUM)},
    1035                 :             :                                 }, /*fAllowNull=*/false, /*fStrict=*/true);
    1036                 :             : 
    1037         [ +  - ]:          97 :                 const Txid txid = Txid::FromUint256(ParseHashO(o, "txid"));
    1038   [ +  -  +  - ]:          97 :                 const int nOutput{o.find_value("vout").getInt<int>()};
    1039         [ +  + ]:          97 :                 if (nOutput < 0) {
    1040   [ +  -  +  - ]:           2 :                     throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout cannot be negative");
    1041                 :             :                 }
    1042         [ +  - ]:          96 :                 prevouts_to_process.emplace_back(COutPoint{txid, static_cast<uint32_t>(nOutput)}, idx);
    1043                 :             :             }
    1044                 :             : 
    1045                 :         182 :             auto make_output = [&output_params, return_spending_tx](const Entry& prevout, const CTransaction* spending_tx = nullptr) {
    1046         [ +  - ]:          96 :                 UniValue o{output_params[prevout.request_index]};
    1047         [ +  + ]:          91 :                 if (spending_tx) {
    1048   [ +  -  +  -  :         172 :                     o.pushKV("spendingtxid", spending_tx->GetHash().ToString());
             +  -  +  - ]
    1049         [ +  + ]:          86 :                     if (return_spending_tx) {
    1050   [ +  -  +  -  :          22 :                         o.pushKV("spendingtx", EncodeHexTx(*spending_tx));
             +  -  +  - ]
    1051                 :             :                     }
    1052                 :             :                 }
    1053                 :          91 :                 return o;
    1054                 :           0 :             };
    1055                 :             : 
    1056   [ -  +  +  - ]:          86 :             std::vector<UniValue> results(output_params.size());
    1057                 :             : 
    1058                 :             :             // Search the mempool first
    1059                 :          86 :             std::vector<Entry> unresolved;
    1060   [ -  +  +  - ]:          86 :             unresolved.reserve(prevouts_to_process.size());
    1061                 :          86 :             {
    1062         [ +  - ]:          86 :                 const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
    1063         [ +  - ]:          86 :                 LOCK(mempool.cs);
    1064                 :             : 
    1065                 :             :                 // Make the result if the spending tx appears in the mempool or this is a mempool_only request
    1066         [ +  + ]:         182 :                 for (const auto& prevout : prevouts_to_process) {
    1067         [ +  - ]:          96 :                     const auto* spending_tx{mempool.GetConflictTx(prevout.outpoint)};
    1068                 :             : 
    1069                 :             :                     // If the outpoint is not spent in the mempool and this is not a mempool-only
    1070                 :             :                     // request, we cannot answer it yet.
    1071         [ +  + ]:          96 :                     if (!spending_tx && !mempool_only) {
    1072         [ +  - ]:          16 :                         unresolved.push_back(prevout);
    1073                 :             :                     } else {
    1074         [ +  - ]:          80 :                         results[prevout.request_index] = make_output(prevout, spending_tx);
    1075                 :             :                     }
    1076                 :             :                 }
    1077                 :           0 :             }
    1078                 :             : 
    1079                 :             :             // mempool_only requests resolve every outpoint above, so only other requests reach the index.
    1080   [ +  +  +  -  :          86 :             if (!unresolved.empty() && (!g_txospenderindex || !g_txospenderindex->BlockUntilSyncedToCurrentChain())) {
             +  -  -  + ]
    1081   [ #  #  #  # ]:           0 :                 throw JSONRPCError(RPC_MISC_ERROR, "Mempool lacks a relevant spend, and txospenderindex is unavailable.");
    1082                 :             :             }
    1083                 :             : 
    1084         [ +  + ]:         102 :             for (const auto& prevout : unresolved) {
    1085         [ +  - ]:          16 :                 const auto spender{g_txospenderindex->FindSpender(prevout.outpoint)};
    1086         [ -  + ]:          16 :                 if (!spender) {
    1087         [ #  # ]:           0 :                     throw JSONRPCError(RPC_MISC_ERROR, spender.error());
    1088                 :             :                 }
    1089                 :             : 
    1090   [ +  -  +  + ]:          16 :                 if (const auto& spender_opt{spender.value()}) {
    1091         [ +  - ]:          11 :                     UniValue o{make_output(prevout, spender_opt->tx.get())};
    1092   [ +  -  +  -  :          22 :                     o.pushKV("blockhash", spender_opt->block_hash.GetHex());
             +  -  +  - ]
    1093                 :          11 :                     results[prevout.request_index] = std::move(o);
    1094                 :          11 :                 } else {
    1095                 :             :                     // Only return the input outpoint itself, which indicates it is unspent.
    1096         [ +  - ]:          10 :                     results[prevout.request_index] = make_output(prevout);
    1097                 :             :                 }
    1098                 :          16 :             }
    1099                 :             : 
    1100                 :          86 :             UniValue result{UniValue::VARR};
    1101   [ -  +  +  - ]:          86 :             result.reserve(results.size());
    1102   [ +  -  +  + ]:         182 :             for (auto& output : results) result.push_back(std::move(output));
    1103                 :         172 :             return result;
    1104   [ +  -  +  -  :         287 :         },
          +  -  +  -  +  
          -  +  -  -  -  
                   -  + ]
    1105   [ +  -  +  -  :       44676 :     };
          +  -  +  -  +  
          -  +  +  +  +  
          +  +  +  +  -  
          -  -  -  -  -  
                   -  - ]
    1106   [ +  -  +  -  :       70956 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  -  -  -  -  
          -  -  -  -  -  
                      - ]
    1107                 :             : 
    1108                 :        1338 : UniValue MempoolInfoToJSON(const CTxMemPool& pool)
    1109                 :             : {
    1110                 :             :     // Make sure this call is atomic in the pool.
    1111                 :        1338 :     LOCK(pool.cs);
    1112                 :        1338 :     UniValue ret(UniValue::VOBJ);
    1113   [ +  -  +  -  :        2676 :     ret.pushKV("loaded", pool.GetLoadTried());
             +  -  +  - ]
    1114   [ +  -  +  -  :        2676 :     ret.pushKV("size", pool.size());
             +  -  +  - ]
    1115   [ +  -  +  -  :        2676 :     ret.pushKV("bytes", pool.GetTotalTxSize());
                   +  - ]
    1116   [ +  -  +  -  :        2676 :     ret.pushKV("usage", pool.DynamicMemoryUsage());
             +  -  +  - ]
    1117   [ +  -  +  -  :        2676 :     ret.pushKV("total_fee", ValueFromAmount(pool.GetTotalFee()));
                   +  - ]
    1118   [ +  -  +  -  :        2676 :     ret.pushKV("maxmempool", pool.m_opts.max_size_bytes);
                   +  - ]
    1119   [ +  -  +  -  :        2676 :     ret.pushKV("mempoolminfee", ValueFromAmount(std::max(pool.GetMinFee(), pool.m_opts.min_relay_feerate).GetFeePerK()));
             +  -  +  - ]
    1120   [ +  -  +  -  :        2676 :     ret.pushKV("minrelaytxfee", ValueFromAmount(pool.m_opts.min_relay_feerate.GetFeePerK()));
                   +  - ]
    1121   [ +  -  +  -  :        2676 :     ret.pushKV("incrementalrelayfee", ValueFromAmount(pool.m_opts.incremental_relay_feerate.GetFeePerK()));
                   +  - ]
    1122   [ +  -  +  -  :        2676 :     ret.pushKV("unbroadcastcount", pool.GetUnbroadcastTxs().size());
             +  -  +  - ]
    1123   [ +  -  +  -  :        2676 :     ret.pushKV("permitbaremultisig", pool.m_opts.permit_bare_multisig);
                   +  - ]
    1124   [ +  +  +  -  :        4012 :     ret.pushKV("maxdatacarriersize", pool.m_opts.max_datacarrier_bytes.value_or(0));
             +  -  +  - ]
    1125   [ +  -  +  -  :        2676 :     ret.pushKV("limitclustercount", pool.m_opts.limits.cluster_count);
                   +  - ]
    1126   [ +  -  +  -  :        2676 :     ret.pushKV("limitclustersize", pool.m_opts.limits.cluster_size_vbytes);
                   +  - ]
    1127   [ +  -  +  -  :        2676 :     ret.pushKV("optimal", pool.m_txgraph->DoWork(0)); // 0 work is a quick check for known optimality
                   +  - ]
    1128   [ +  -  +  -  :        1338 :     if (IsDeprecatedRPCEnabled("fullrbf")) {
                   +  + ]
    1129   [ +  -  +  -  :           6 :         ret.pushKV("fullrbf", true);
                   +  - ]
    1130                 :             :     }
    1131         [ +  - ]:        1338 :     return ret;
    1132                 :        1338 : }
    1133                 :             : 
    1134                 :        3872 : static RPCMethod getmempoolinfo()
    1135                 :             : {
    1136                 :        3872 :     return RPCMethod{"getmempoolinfo",
    1137         [ +  - ]:        7744 :         "Returns details on the active state of the TX memory pool.",
    1138                 :             :         {},
    1139         [ +  - ]:        7744 :         RPCResult{
    1140         [ +  - ]:        7744 :             RPCResult::Type::OBJ, "", "",
    1141                 :        3872 :             [](){
    1142                 :        3872 :                 std::vector<RPCResult> list = {
    1143   [ +  -  +  - ]:        7744 :                     {RPCResult::Type::BOOL, "loaded", "True if the initial load attempt of the persisted mempool finished"},
    1144   [ +  -  +  - ]:        7744 :                     {RPCResult::Type::NUM, "size", "Current tx count"},
    1145   [ +  -  +  - ]:        7744 :                     {RPCResult::Type::NUM, "bytes", "Sum of all virtual transaction sizes as defined in BIP 141. Differs from actual serialized size because witness data is discounted"},
    1146   [ +  -  +  - ]:        7744 :                     {RPCResult::Type::NUM, "usage", "Total memory usage for the mempool"},
    1147   [ +  -  +  - ]:        7744 :                     {RPCResult::Type::STR_AMOUNT, "total_fee", "Total fees for the mempool in " + CURRENCY_UNIT + ", ignoring modified fees through prioritisetransaction"},
    1148   [ +  -  +  - ]:        7744 :                     {RPCResult::Type::NUM, "maxmempool", "Maximum memory usage for the mempool"},
    1149   [ +  -  +  - ]:        7744 :                     {RPCResult::Type::STR_AMOUNT, "mempoolminfee", "Minimum fee rate in " + CURRENCY_UNIT + "/kvB for tx to be accepted. Is the maximum of minrelaytxfee and minimum mempool fee"},
    1150   [ +  -  +  - ]:        7744 :                     {RPCResult::Type::STR_AMOUNT, "minrelaytxfee", "Current minimum relay fee for transactions"},
    1151   [ +  -  +  - ]:        7744 :                     {RPCResult::Type::STR_AMOUNT, "incrementalrelayfee", "minimum fee rate increment for mempool limiting or replacement in " + CURRENCY_UNIT + "/kvB"},
    1152   [ +  -  +  - ]:        7744 :                     {RPCResult::Type::NUM, "unbroadcastcount", "Current number of transactions that haven't passed initial broadcast yet"},
    1153   [ +  -  +  - ]:        7744 :                     {RPCResult::Type::BOOL, "permitbaremultisig", "True if the mempool accepts transactions with bare multisig outputs"},
    1154   [ +  -  +  - ]:        7744 :                     {RPCResult::Type::NUM, "maxdatacarriersize", "Maximum number of bytes that can be used by OP_RETURN outputs in the mempool"},
    1155   [ +  -  +  - ]:        7744 :                     {RPCResult::Type::NUM, "limitclustercount", "Maximum number of transactions that can be in a cluster (configured by -limitclustercount)"},
    1156   [ +  -  +  - ]:        7744 :                     {RPCResult::Type::NUM, "limitclustersize", "Maximum size of a cluster in virtual bytes (configured by -limitclustersize)"},
    1157   [ +  -  +  - ]:        7744 :                     {RPCResult::Type::BOOL, "optimal", "If the mempool is in a known-optimal transaction ordering"},
    1158   [ +  -  +  +  :      123904 :                 };
                   -  - ]
    1159   [ +  -  +  -  :        3872 :                 if (IsDeprecatedRPCEnabled("fullrbf")) {
                   +  + ]
    1160         [ +  - ]:           5 :                     list.emplace_back(RPCResult::Type::BOOL, "fullrbf", "True if the mempool accepts RBF without replaceability signaling inspection (DEPRECATED)");
    1161                 :             :                 }
    1162                 :        3872 :                 return list;
    1163   [ +  -  +  -  :      123904 :             }()
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  -  
                      - ]
    1164         [ +  - ]:        7744 :             },
    1165                 :        3872 :         RPCExamples{
    1166   [ +  -  +  -  :        7744 :             HelpExampleCli("getmempoolinfo", "")
                   +  - ]
    1167   [ +  -  +  -  :       15488 :             + HelpExampleRpc("getmempoolinfo", "")
             +  -  +  - ]
    1168         [ +  - ]:        3872 :         },
    1169                 :        3872 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
    1170                 :             : {
    1171                 :        1336 :     return MempoolInfoToJSON(EnsureAnyMemPool(request.context));
    1172                 :             : },
    1173   [ +  -  +  - ]:       15488 :     };
    1174                 :             : }
    1175                 :             : 
    1176                 :        2539 : static RPCMethod importmempool()
    1177                 :             : {
    1178                 :        2539 :     return RPCMethod{
    1179                 :        2539 :         "importmempool",
    1180         [ +  - ]:        5078 :         "Import a mempool.dat file and attempt to add its contents to the mempool.\n"
    1181                 :             :         "Warning: Importing untrusted files is dangerous, especially if metadata from the file is taken over.",
    1182                 :             :         {
    1183   [ +  -  +  - ]:        5078 :             {"filepath", RPCArg::Type::STR, RPCArg::Optional::NO, "The mempool file"},
    1184         [ +  - ]:        5078 :             {"options",
    1185                 :             :              RPCArg::Type::OBJ_NAMED_PARAMS,
    1186                 :        2539 :              RPCArg::Optional::OMITTED,
    1187         [ +  - ]:        5078 :              "",
    1188                 :             :              {
    1189   [ +  -  +  - ]:        5078 :                  {"use_current_time", RPCArg::Type::BOOL, RPCArg::Default{true},
    1190         [ +  - ]:        5078 :                   "Whether to use the current system time or use the entry time metadata from the mempool file.\n"
    1191                 :             :                   "Warning: Importing untrusted metadata may lead to unexpected issues and undesirable behavior."},
    1192   [ +  -  +  - ]:        5078 :                  {"apply_fee_delta_priority", RPCArg::Type::BOOL, RPCArg::Default{false},
    1193         [ +  - ]:        5078 :                   "Whether to apply the fee delta metadata from the mempool file.\n"
    1194                 :             :                   "It will be added to any existing fee deltas.\n"
    1195                 :             :                   "The fee delta can be set by the prioritisetransaction RPC.\n"
    1196                 :             :                   "Warning: Importing untrusted metadata may lead to unexpected issues and undesirable behavior.\n"
    1197                 :             :                   "Only set this bool if you understand what it does."},
    1198   [ +  -  +  - ]:        5078 :                  {"apply_unbroadcast_set", RPCArg::Type::BOOL, RPCArg::Default{false},
    1199         [ +  - ]:        5078 :                   "Whether to apply the unbroadcast set metadata from the mempool file.\n"
    1200                 :             :                   "Warning: Importing untrusted metadata may lead to unexpected issues and undesirable behavior."},
    1201                 :             :              },
    1202         [ +  - ]:        2539 :              RPCArgOptions{.oneline_description = "options"}},
    1203                 :             :         },
    1204   [ +  -  +  -  :        5078 :         RPCResult{RPCResult::Type::OBJ, "", "", std::vector<RPCResult>{}},
             +  -  +  - ]
    1205   [ +  -  +  -  :        7617 :         RPCExamples{HelpExampleCli("importmempool", "/path/to/mempool.dat") + HelpExampleRpc("importmempool", R"("/path/to/mempool.dat")")},
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
    1206                 :        2539 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue {
    1207                 :           3 :             const NodeContext& node{EnsureAnyNodeContext(request.context)};
    1208                 :             : 
    1209                 :           3 :             CTxMemPool& mempool{EnsureMemPool(node)};
    1210                 :           3 :             ChainstateManager& chainman = EnsureChainman(node);
    1211                 :           3 :             Chainstate& chainstate = chainman.ActiveChainstate();
    1212                 :             : 
    1213         [ -  + ]:           3 :             if (chainman.IsInitialBlockDownload()) {
    1214   [ #  #  #  # ]:           0 :                 throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Can only import the mempool after the block download and sync is done.");
    1215                 :             :             }
    1216                 :             : 
    1217                 :           3 :             const fs::path load_path{fs::u8path(self.Arg<std::string_view>("filepath"))};
    1218   [ +  -  +  -  :           3 :             const UniValue& use_current_time{request.params[1]["use_current_time"]};
                   +  - ]
    1219   [ +  -  +  -  :           3 :             const UniValue& apply_fee_delta{request.params[1]["apply_fee_delta_priority"]};
                   +  - ]
    1220   [ +  -  +  -  :           3 :             const UniValue& apply_unbroadcast{request.params[1]["apply_unbroadcast_set"]};
                   +  - ]
    1221         [ -  + ]:           3 :             node::ImportMempoolOptions opts{
    1222   [ -  +  -  - ]:           3 :                 .use_current_time = use_current_time.isNull() ? true : use_current_time.get_bool(),
    1223   [ +  +  +  - ]:           3 :                 .apply_fee_delta_priority = apply_fee_delta.isNull() ? false : apply_fee_delta.get_bool(),
    1224   [ +  +  +  - ]:           3 :                 .apply_unbroadcast_set = apply_unbroadcast.isNull() ? false : apply_unbroadcast.get_bool(),
    1225   [ -  +  +  +  :           5 :             };
                   +  + ]
    1226                 :             : 
    1227   [ +  -  -  + ]:           3 :             if (!node::LoadMempool(mempool, load_path, chainstate, std::move(opts))) {
    1228   [ #  #  #  # ]:           0 :                 throw JSONRPCError(RPC_MISC_ERROR, "Unable to import mempool file, see debug log for details.");
    1229                 :             :             }
    1230                 :             : 
    1231                 :           3 :             UniValue ret{UniValue::VOBJ};
    1232                 :           3 :             return ret;
    1233                 :           6 :         },
    1234   [ +  -  +  -  :       27929 :     };
          +  -  +  +  +  
             +  -  -  -  
                      - ]
    1235   [ +  -  +  -  :       22851 : }
          +  -  +  -  +  
             -  -  -  -  
                      - ]
    1236                 :             : 
    1237                 :        2540 : static RPCMethod savemempool()
    1238                 :             : {
    1239                 :        2540 :     return RPCMethod{
    1240                 :        2540 :         "savemempool",
    1241         [ +  - ]:        5080 :         "Dumps the mempool to disk. It will fail until the previous dump is fully loaded.\n",
    1242                 :             :         {},
    1243         [ +  - ]:        5080 :         RPCResult{
    1244         [ +  - ]:        5080 :             RPCResult::Type::OBJ, "", "",
    1245                 :             :             {
    1246   [ +  -  +  - ]:        5080 :                 {RPCResult::Type::STR, "filename", "the directory and file where the mempool was saved"},
    1247   [ +  -  +  -  :       10160 :             }},
             +  +  -  - ]
    1248                 :        2540 :         RPCExamples{
    1249   [ +  -  +  -  :        5080 :             HelpExampleCli("savemempool", "")
                   +  - ]
    1250   [ +  -  +  -  :       10160 :             + HelpExampleRpc("savemempool", "")
             +  -  +  - ]
    1251         [ +  - ]:        2540 :         },
    1252                 :        2540 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
    1253                 :             : {
    1254                 :           4 :     const ArgsManager& args{EnsureAnyArgsman(request.context)};
    1255                 :           4 :     const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
    1256                 :             : 
    1257         [ -  + ]:           4 :     if (!mempool.GetLoadTried()) {
    1258   [ #  #  #  # ]:           0 :         throw JSONRPCError(RPC_MISC_ERROR, "The mempool was not loaded yet");
    1259                 :             :     }
    1260                 :             : 
    1261                 :           4 :     const fs::path& dump_path = MempoolPath(args);
    1262                 :             : 
    1263   [ +  -  +  + ]:           4 :     if (!DumpMempool(mempool, dump_path)) {
    1264   [ +  -  +  - ]:           2 :         throw JSONRPCError(RPC_MISC_ERROR, "Unable to dump mempool to disk");
    1265                 :             :     }
    1266                 :             : 
    1267                 :           3 :     UniValue ret(UniValue::VOBJ);
    1268   [ +  -  +  -  :           6 :     ret.pushKV("filename", dump_path.utf8string());
             +  -  +  - ]
    1269                 :             : 
    1270                 :           6 :     return ret;
    1271                 :           0 : },
    1272   [ +  -  +  - ]:       10160 :     };
    1273         [ +  - ]:        5080 : }
    1274                 :             : 
    1275                 :        5508 : static std::vector<RPCResult> OrphanDescription()
    1276                 :             : {
    1277                 :        5508 :     return {
    1278   [ +  -  +  - ]:       11016 :         RPCResult{RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
    1279   [ +  -  +  - ]:       11016 :         RPCResult{RPCResult::Type::STR_HEX, "wtxid", "The transaction witness hash in hex"},
    1280   [ +  -  +  - ]:       11016 :         RPCResult{RPCResult::Type::NUM, "bytes", "The serialized transaction size in bytes"},
    1281   [ +  -  +  - ]:       11016 :         RPCResult{RPCResult::Type::NUM, "vsize", "(DEPRECATED) use vsize_bip141 instead. The virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted."},
    1282   [ +  -  +  - ]:       11016 :         RPCResult{RPCResult::Type::NUM, "vsize_bip141", "The virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted."},
    1283   [ +  -  +  - ]:       11016 :         RPCResult{RPCResult::Type::NUM, "weight", "The transaction weight as defined in BIP 141."},
    1284   [ +  -  +  - ]:       11016 :         RPCResult{RPCResult::Type::ARR, "from", "",
    1285                 :             :         {
    1286   [ +  -  +  - ]:       11016 :             RPCResult{RPCResult::Type::NUM, "peer_id", "Peer ID"},
    1287   [ +  -  +  +  :       16524 :         }},
                   -  - ]
    1288   [ +  -  +  +  :       55080 :     };
                   -  - ]
    1289   [ +  -  +  -  :       88128 : }
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  -  - ]
    1290                 :             : 
    1291                 :          43 : static UniValue OrphanToJSON(const node::TxOrphanage::OrphanInfo& orphan)
    1292                 :             : {
    1293                 :          43 :     UniValue o(UniValue::VOBJ);
    1294   [ +  -  +  -  :          86 :     o.pushKV("txid", orphan.tx->GetHash().ToString());
             +  -  +  - ]
    1295   [ +  -  +  -  :          86 :     o.pushKV("wtxid", orphan.tx->GetWitnessHash().ToString());
             +  -  +  - ]
    1296   [ +  -  +  -  :          86 :     o.pushKV("bytes", orphan.tx->ComputeTotalSize());
             +  -  +  - ]
    1297   [ +  -  +  -  :          86 :     o.pushKV("vsize", GetVirtualTransactionSize(*orphan.tx));
             +  -  +  - ]
    1298   [ +  -  +  -  :          86 :     o.pushKV("vsize_bip141", GetVirtualTransactionSize(*orphan.tx));
             +  -  +  - ]
    1299   [ +  -  +  -  :          86 :     o.pushKV("weight", GetTransactionWeight(*orphan.tx));
                   +  - ]
    1300                 :          43 :     UniValue from(UniValue::VARR);
    1301         [ +  + ]:          92 :     for (const auto fromPeer: orphan.announcers) {
    1302   [ +  -  +  - ]:          49 :         from.push_back(fromPeer);
    1303                 :             :     }
    1304   [ +  -  +  -  :          86 :     o.pushKV("from", from);
                   +  - ]
    1305                 :          43 :     return o;
    1306                 :          43 : }
    1307                 :             : 
    1308                 :        2754 : static RPCMethod getorphantxs()
    1309                 :             : {
    1310                 :        2754 :     return RPCMethod{
    1311                 :        2754 :         "getorphantxs",
    1312         [ +  - ]:        5508 :         "Shows transactions in the tx orphanage.\n"
    1313                 :             :         "\nEXPERIMENTAL warning: this call may be changed in future releases.\n",
    1314                 :             :         {
    1315   [ +  -  +  -  :        8262 :             {"verbosity", RPCArg::Type::NUM, RPCArg::Default{0}, "0 for an array of txids (may contain duplicates), 1 for an array of objects with tx details, and 2 for details from (1) and tx hex",
                   +  - ]
    1316         [ +  - ]:        5508 :              RPCArgOptions{.skip_type_check = true}},
    1317                 :             :         },
    1318                 :             :         {
    1319         [ +  - ]:        2754 :             RPCResult{"for verbose = 0",
    1320   [ +  -  +  - ]:        5508 :                 RPCResult::Type::ARR, "", "",
    1321                 :             :                 {
    1322   [ +  -  +  - ]:        5508 :                     {RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
    1323   [ +  -  +  +  :       11016 :                 }},
                   -  - ]
    1324         [ +  - ]:        5508 :             RPCResult{"for verbose = 1",
    1325   [ +  -  +  - ]:        5508 :                 RPCResult::Type::ARR, "", "",
    1326                 :             :                 {
    1327   [ +  -  +  -  :        5508 :                     {RPCResult::Type::OBJ, "", "", OrphanDescription()},
                   +  - ]
    1328   [ +  -  +  +  :        8262 :                 }},
                   -  - ]
    1329         [ +  - ]:        5508 :             RPCResult{"for verbose = 2",
    1330   [ +  -  +  - ]:        5508 :                 RPCResult::Type::ARR, "", "",
    1331                 :             :                 {
    1332   [ +  -  +  - ]:        5508 :                     {RPCResult::Type::OBJ, "", "",
    1333   [ +  -  +  -  :       13770 :                         Cat<std::vector<RPCResult>>(
             +  +  -  - ]
    1334         [ +  - ]:        5508 :                             OrphanDescription(),
    1335   [ +  -  +  - ]:        5508 :                             {{RPCResult::Type::STR_HEX, "hex", "The serialized, hex-encoded transaction data"}}
    1336                 :             :                         )
    1337                 :             :                     },
    1338   [ +  -  +  +  :        8262 :                 }},
                   -  - ]
    1339                 :             :         },
    1340                 :        2754 :         RPCExamples{
    1341   [ +  -  +  -  :        5508 :             HelpExampleCli("getorphantxs", "2")
                   +  - ]
    1342   [ +  -  +  -  :       11016 :             + HelpExampleRpc("getorphantxs", "2")
                   +  - ]
    1343         [ +  - ]:        2754 :         },
    1344                 :        2754 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
    1345                 :             :         {
    1346                 :         228 :             const NodeContext& node = EnsureAnyNodeContext(request.context);
    1347                 :         228 :             PeerManager& peerman = EnsurePeerman(node);
    1348                 :         228 :             std::vector<node::TxOrphanage::OrphanInfo> orphanage = peerman.GetOrphanTransactions();
    1349                 :             : 
    1350   [ +  -  +  + ]:         228 :             int verbosity{ParseVerbosity(request.params[0], /*default_verbosity=*/0, /*allow_bool=*/false)};
    1351                 :             : 
    1352                 :         226 :             UniValue ret(UniValue::VARR);
    1353                 :             : 
    1354         [ +  + ]:         226 :             if (verbosity == 0) {
    1355         [ +  + ]:       18492 :                 for (auto const& orphan : orphanage) {
    1356   [ +  -  +  -  :       18302 :                     ret.push_back(orphan.tx->GetHash().ToString());
                   +  - ]
    1357                 :             :                 }
    1358         [ +  + ]:          36 :             } else if (verbosity == 1) {
    1359         [ +  + ]:          58 :                 for (auto const& orphan : orphanage) {
    1360   [ +  -  +  - ]:          33 :                     ret.push_back(OrphanToJSON(orphan));
    1361                 :             :                 }
    1362         [ +  + ]:          11 :             } else if (verbosity == 2) {
    1363         [ +  + ]:          19 :                 for (auto const& orphan : orphanage) {
    1364         [ +  - ]:          10 :                     UniValue o{OrphanToJSON(orphan)};
    1365   [ +  -  +  -  :          20 :                     o.pushKV("hex", EncodeHexTx(*orphan.tx));
             +  -  +  - ]
    1366   [ +  -  +  - ]:          10 :                     ret.push_back(o);
    1367                 :          10 :                 }
    1368                 :             :             } else {
    1369   [ +  -  +  -  :           4 :                 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid verbosity value " + ToString(verbosity));
                   +  - ]
    1370                 :             :             }
    1371                 :             : 
    1372                 :         224 :             return ret;
    1373                 :         230 :         },
    1374   [ +  -  +  -  :       30294 :     };
          +  -  +  -  +  
          +  +  +  -  -  
                   -  - ]
    1375   [ +  -  +  -  :       41310 : }
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  -  - ]
    1376                 :             : 
    1377                 :        2655 : static RPCMethod submitpackage()
    1378                 :             : {
    1379                 :        2655 :     return RPCMethod{"submitpackage",
    1380         [ +  - ]:        5310 :         "Submit a package of raw transactions (serialized, hex-encoded) to local node.\n"
    1381                 :             :         "The package will be validated according to consensus and mempool policy rules. If any transaction passes, it will be accepted to mempool.\n"
    1382                 :             :         "This RPC is experimental and the interface may be unstable. Refer to doc/policy/packages.md for documentation on package policies.\n"
    1383                 :             :         "Warning: successful submission does not mean the transactions will propagate throughout the network.\n"
    1384                 :             :         ,
    1385                 :             :         {
    1386   [ +  -  +  - ]:        5310 :             {"package", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of raw transactions.\n"
    1387                 :             :                 "The package must consist of a transaction with (some, all, or none of) its unconfirmed parents. A single transaction is permitted.\n"
    1388                 :             :                 "None of the parents may depend on each other. Parents that are already in mempool do not need to be present in the package.\n"
    1389                 :             :                 "The package must be topologically sorted, with the child being the last element in the array if there are multiple elements.",
    1390                 :             :                 {
    1391   [ +  -  +  - ]:        5310 :                     {"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
    1392                 :             :                 },
    1393                 :             :             },
    1394   [ +  -  +  -  :        5310 :             {"maxfeerate", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK())},
                   +  - ]
    1395         [ +  - ]:        5310 :              "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT +
    1396                 :        2655 :                  "/kvB.\nFee rates larger than 1BTC/kvB are rejected.\nSet to 0 to accept any fee rate."},
    1397   [ +  -  +  -  :        5310 :             {"maxburnamount", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_BURN_AMOUNT)},
                   +  - ]
    1398         [ +  - ]:        5310 :              "Reject transactions with provably unspendable outputs (e.g. 'datacarrier' outputs that use the OP_RETURN opcode) greater than the specified value, expressed in " + CURRENCY_UNIT + ".\n"
    1399                 :             :              "If burning funds through unspendable outputs is desired, increase this value.\n"
    1400                 :        2655 :              "This check is based on heuristics and does not guarantee spendability of outputs.\n"
    1401                 :             :             },
    1402                 :             :         },
    1403         [ +  - ]:        5310 :         RPCResult{
    1404   [ +  -  +  - ]:        5310 :             RPCResult::Type::OBJ, "", "",
    1405                 :             :             {
    1406   [ +  -  +  - ]:        5310 :                 {RPCResult::Type::STR, "package_msg", "The transaction package result message. \"success\" indicates all transactions were accepted into or are already in the mempool."},
    1407   [ +  -  +  - ]:        5310 :                 {RPCResult::Type::OBJ_DYN, "tx-results", "The transaction results keyed by wtxid. An entry is returned for every submitted wtxid.",
    1408                 :             :                 {
    1409   [ +  -  +  - ]:        5310 :                     {RPCResult::Type::OBJ, "wtxid", "transaction wtxid", {
    1410   [ +  -  +  - ]:        5310 :                         {RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
    1411   [ +  -  +  - ]:        5310 :                         {RPCResult::Type::STR_HEX, "other-wtxid", /*optional=*/true, "The wtxid of a different transaction with the same txid but different witness found in the mempool. This means the submitted transaction was ignored."},
    1412   [ +  -  +  - ]:        5310 :                         {RPCResult::Type::NUM, "vsize_adjusted", /*optional=*/true, "Maximum of sigop-adjusted size (-bytespersigop) and virtual transaction size as defined in BIP 141."},
    1413   [ +  -  +  - ]:        5310 :                         {RPCResult::Type::NUM, "vsize", /*optional=*/true, "(DEPRECATED) Was previously erroneously described as the BIP 141 vsize, but is actually sigops-adjusted vsize.\n"
    1414                 :             :                                                                     "Use vsize_bip141 to actually get that behavior or switch to the explicit vsize_adjusted for retained behavior."},
    1415   [ +  -  +  - ]:        5310 :                         {RPCResult::Type::NUM, "vsize_bip141", /*optional=*/true, "Virtual transaction size as defined in BIP 141."},
    1416   [ +  -  +  - ]:        5310 :                         {RPCResult::Type::OBJ, "fees", /*optional=*/true, "Transaction fees", {
    1417   [ +  -  +  - ]:        5310 :                             {RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT},
    1418   [ +  -  +  - ]:        5310 :                             {RPCResult::Type::STR_AMOUNT, "effective-feerate", /*optional=*/true, "if the transaction was not already in the mempool, the effective feerate in " + CURRENCY_UNIT + " per KvB. For example, the package feerate and/or feerate with modified fees from prioritisetransaction."},
    1419   [ +  -  +  - ]:        5310 :                             {RPCResult::Type::ARR, "effective-includes", /*optional=*/true, "if effective-feerate is provided, the wtxids of the transactions whose fees and vsizes are included in effective-feerate.",
    1420   [ +  -  +  - ]:        5310 :                                 {{RPCResult::Type::STR_HEX, "", "transaction wtxid in hex"},
    1421                 :             :                             }},
    1422                 :             :                         }},
    1423   [ +  -  +  - ]:        5310 :                         {RPCResult::Type::STR, "error", /*optional=*/true, "Error string if rejected from mempool, or \"package-not-validated\" when the package aborts before any per-tx processing."},
    1424                 :             :                     }}
    1425                 :             :                 }},
    1426   [ +  -  +  - ]:        5310 :                 {RPCResult::Type::ARR, "replaced-transactions", /*optional=*/true, "List of txids of replaced transactions",
    1427                 :             :                 {
    1428   [ +  -  +  - ]:        5310 :                     {RPCResult::Type::STR_HEX, "", "The transaction id"},
    1429                 :             :                 }},
    1430                 :             :             },
    1431   [ +  -  +  -  :      103545 :         },
          +  -  +  -  +  
          -  +  -  +  -  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  -  -  -  
          -  -  -  -  -  
             -  -  -  - ]
    1432                 :        2655 :         RPCExamples{
    1433   [ +  -  +  -  :        5310 :             HelpExampleRpc("submitpackage", R"(["raw-parent-tx-1", "raw-parent-tx-2", "raw-child-tx"])") +
                   +  - ]
    1434   [ +  -  +  -  :        7965 :             HelpExampleCli("submitpackage", R"('["raw-tx-without-unconfirmed-parents"]')")
             +  -  +  - ]
    1435         [ +  - ]:        2655 :         },
    1436                 :        2655 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
    1437                 :             :         {
    1438                 :         119 :             const UniValue raw_transactions = request.params[0].get_array();
    1439   [ -  +  +  +  :         119 :             if (raw_transactions.empty() || raw_transactions.size() > MAX_PACKAGE_COUNT) {
                   +  + ]
    1440                 :           2 :                 throw JSONRPCError(RPC_INVALID_PARAMETER,
    1441   [ +  -  +  -  :           6 :                                    "Array must contain between 1 and " + ToString(MAX_PACKAGE_COUNT) + " transactions.");
                   +  - ]
    1442                 :             :             }
    1443                 :             : 
    1444                 :             :             // Fee check needs to be run with chainstate and package context
    1445   [ +  -  +  - ]:         117 :             const CFeeRate max_raw_tx_fee_rate{ParseFeeRate(self.Arg<UniValue>("maxfeerate"))};
    1446         [ +  + ]:         117 :             std::optional<CFeeRate> client_maxfeerate{max_raw_tx_fee_rate};
    1447                 :             :             // 0-value is special; it's mapped to no sanity check
    1448         [ +  + ]:         117 :             if (max_raw_tx_fee_rate == CFeeRate(0)) {
    1449                 :          29 :                 client_maxfeerate = std::nullopt;
    1450                 :             :             }
    1451                 :             : 
    1452                 :             :             // Burn sanity check is run with no context
    1453   [ +  -  +  +  :         117 :             const CAmount max_burn_amount = request.params[2].isNull() ? 0 : AmountFromValue(request.params[2]);
             +  -  +  - ]
    1454                 :             : 
    1455                 :         117 :             std::vector<CTransactionRef> txns;
    1456   [ -  +  +  - ]:         117 :             txns.reserve(raw_transactions.size());
    1457   [ +  -  +  + ]:         497 :             for (const auto& rawtx : raw_transactions.getValues()) {
    1458         [ +  - ]:         382 :                 CMutableTransaction mtx;
    1459   [ +  -  +  -  :         382 :                 if (!DecodeHexTx(mtx, rawtx.get_str())) {
                   +  + ]
    1460                 :           1 :                     throw JSONRPCError(RPC_DESERIALIZATION_ERROR,
    1461   [ +  -  +  -  :           3 :                                        "TX decode failed: " + rawtx.get_str() + " Make sure the tx has at least one input.");
                   +  - ]
    1462                 :             :                 }
    1463                 :             : 
    1464         [ +  + ]:         895 :                 for (const auto& out : mtx.vout) {
    1465   [ +  +  +  -  :         515 :                     if((out.scriptPubKey.IsUnspendable() || !out.scriptPubKey.HasValidOps()) && out.nValue > max_burn_amount) {
             -  +  +  + ]
    1466   [ +  -  +  - ]:           2 :                         throw JSONRPCTransactionError(TransactionError::MAX_BURN_EXCEEDED);
    1467                 :             :                     }
    1468                 :             :                 }
    1469                 :             : 
    1470   [ +  -  +  - ]:        1140 :                 txns.emplace_back(MakeTransactionRef(std::move(mtx)));
    1471                 :         382 :             }
    1472         [ +  - ]:         115 :             CHECK_NONFATAL(!txns.empty());
    1473   [ -  +  +  +  :         115 :             if (txns.size() > 1 && !IsChildWithParentsTree(txns)) {
             +  -  +  + ]
    1474   [ +  -  +  - ]:           4 :                 throw JSONRPCTransactionError(TransactionError::INVALID_PACKAGE, "package topology disallowed. not child-with-parents or parents depend on each other.");
    1475                 :             :             }
    1476                 :             : 
    1477         [ +  - ]:         113 :             NodeContext& node = EnsureAnyNodeContext(request.context);
    1478         [ +  - ]:         113 :             CTxMemPool& mempool = EnsureMemPool(node);
    1479   [ +  -  +  - ]:         113 :             Chainstate& chainstate = EnsureChainman(node).ActiveChainstate();
    1480   [ +  -  +  - ]:         339 :             const auto package_result = WITH_LOCK(::cs_main, return ProcessNewPackage(chainstate, mempool, txns, /*test_accept=*/ false, client_maxfeerate));
    1481                 :             : 
    1482         [ +  - ]:         113 :             std::string package_msg = "success";
    1483                 :             : 
    1484                 :             :             // First catch package-wide errors, continue if we can
    1485   [ +  -  +  - ]:         113 :             switch(package_result.m_state.GetResult()) {
    1486                 :          67 :                 case PackageValidationResult::PCKG_RESULT_UNSET:
    1487                 :          67 :                 {
    1488                 :             :                     // Belt-and-suspenders check; everything should be successful here
    1489   [ -  +  +  - ]:          67 :                     CHECK_NONFATAL(package_result.m_tx_results.size() == txns.size());
    1490         [ +  + ]:         295 :                     for (const auto& tx : txns) {
    1491   [ +  -  +  - ]:         228 :                         CHECK_NONFATAL(mempool.exists(tx->GetHash()));
    1492                 :             :                     }
    1493                 :             :                     break;
    1494                 :             :                 }
    1495                 :           0 :                 case PackageValidationResult::PCKG_MEMPOOL_ERROR:
    1496                 :           0 :                 {
    1497                 :             :                     // This only happens with internal bug; user should stop and report
    1498                 :           0 :                     throw JSONRPCTransactionError(TransactionError::MEMPOOL_ERROR,
    1499   [ #  #  #  # ]:           0 :                         package_result.m_state.GetRejectReason());
    1500                 :             :                 }
    1501                 :          46 :                 case PackageValidationResult::PCKG_POLICY:
    1502                 :          46 :                 case PackageValidationResult::PCKG_TX:
    1503                 :          46 :                 {
    1504                 :             :                     // Package-wide error we want to return, but we also want to return individual responses
    1505         [ +  - ]:          46 :                     package_msg = package_result.m_state.ToString();
    1506   [ -  +  +  +  :          48 :                     CHECK_NONFATAL(package_result.m_tx_results.size() == txns.size() ||
             +  -  +  - ]
    1507                 :             :                             package_result.m_tx_results.empty());
    1508                 :             :                     break;
    1509                 :             :                 }
    1510                 :             :             }
    1511                 :             : 
    1512                 :         113 :             size_t num_broadcast{0};
    1513         [ +  + ]:         485 :             for (const auto& tx : txns) {
    1514                 :             :                 // We don't want to re-submit the txn for validation in BroadcastTransaction
    1515   [ +  -  +  + ]:         372 :                 if (!mempool.exists(tx->GetHash())) {
    1516                 :          82 :                     continue;
    1517                 :             :                 }
    1518                 :             : 
    1519                 :             :                 // We do not expect an error here; we are only broadcasting things already/still in mempool
    1520         [ +  - ]:         290 :                 std::string err_string;
    1521   [ +  -  +  - ]:         290 :                 const auto err = BroadcastTransaction(node,
    1522                 :             :                                                       tx,
    1523                 :             :                                                       err_string,
    1524         [ +  - ]:         290 :                                                       /*max_tx_fee=*/0,
    1525                 :             :                                                       node::TxBroadcast::MEMPOOL_AND_BROADCAST_TO_ALL,
    1526                 :             :                                                       /*wait_callback=*/true);
    1527         [ -  + ]:         290 :                 if (err != TransactionError::OK) {
    1528                 :           0 :                     throw JSONRPCTransactionError(err,
    1529         [ #  # ]:           0 :                         strprintf("transaction broadcast failed: %s (%d transactions were broadcast successfully)",
    1530         [ #  # ]:           0 :                             err_string, num_broadcast));
    1531                 :             :                 }
    1532                 :         290 :                 num_broadcast++;
    1533                 :         290 :             }
    1534                 :             : 
    1535                 :         113 :             UniValue rpc_result{UniValue::VOBJ};
    1536   [ +  -  +  -  :         226 :             rpc_result.pushKV("package_msg", package_msg);
                   +  - ]
    1537                 :         226 :             UniValue tx_result_map{UniValue::VOBJ};
    1538                 :         226 :             std::set<Txid> replaced_txids;
    1539         [ +  + ]:         485 :             for (const auto& tx : txns) {
    1540                 :         372 :                 UniValue result_inner{UniValue::VOBJ};
    1541   [ +  -  +  -  :         744 :                 result_inner.pushKV("txid", tx->GetHash().GetHex());
             +  -  +  - ]
    1542         [ +  - ]:         372 :                 const auto wtxid_hex = tx->GetWitnessHash().GetHex();
    1543                 :         372 :                 auto it = package_result.m_tx_results.find(tx->GetWitnessHash());
    1544         [ +  + ]:         372 :                 if (it == package_result.m_tx_results.end()) {
    1545                 :             :                     // No per-tx result for this wtxid
    1546                 :             :                     // Current invariant: per-tx results are all-or-none (every member or empty on package abort).
    1547                 :             :                     // If any exist yet this one is missing, it's an unexpected partial map.
    1548         [ +  - ]:           6 :                     CHECK_NONFATAL(package_result.m_tx_results.empty());
    1549   [ +  -  +  -  :          12 :                     result_inner.pushKV("error", "package-not-validated");
                   +  - ]
    1550   [ -  +  +  - ]:          18 :                     tx_result_map.pushKV(wtxid_hex, std::move(result_inner));
    1551                 :           6 :                     continue;
    1552                 :             :                 }
    1553   [ +  +  +  - ]:         366 :                 const auto& tx_result = it->second;
    1554   [ +  +  +  - ]:         366 :                 switch(it->second.m_result_type) {
    1555                 :           1 :                 case MempoolAcceptResult::ResultType::DIFFERENT_WITNESS:
    1556   [ +  -  +  -  :           2 :                     result_inner.pushKV("other-wtxid", it->second.m_other_wtxid.value().GetHex());
          +  -  +  -  +  
                      - ]
    1557                 :           1 :                     break;
    1558                 :          77 :                 case MempoolAcceptResult::ResultType::INVALID:
    1559   [ +  -  +  -  :         154 :                     result_inner.pushKV("error", it->second.m_state.ToString());
             +  -  +  - ]
    1560                 :          77 :                     break;
    1561                 :         288 :                 case MempoolAcceptResult::ResultType::VALID:
    1562                 :         288 :                 case MempoolAcceptResult::ResultType::MEMPOOL_ENTRY:
    1563   [ +  -  +  -  :         576 :                     result_inner.pushKV("vsize_adjusted", it->second.m_vsize.value());
             +  -  +  - ]
    1564   [ +  -  +  -  :         576 :                     result_inner.pushKV("vsize", it->second.m_vsize.value());
             +  -  +  - ]
    1565   [ +  -  +  -  :         576 :                     result_inner.pushKV("vsize_bip141", GetVirtualTransactionSize(*tx));
             +  -  +  - ]
    1566                 :         288 :                     UniValue fees(UniValue::VOBJ);
    1567   [ +  -  +  -  :         576 :                     fees.pushKV("base", ValueFromAmount(it->second.m_base_fees.value()));
             +  -  +  - ]
    1568         [ +  + ]:         288 :                     if (tx_result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
    1569                 :             :                         // Effective feerate is not provided for MEMPOOL_ENTRY transactions even
    1570                 :             :                         // though modified fees is known, because it is unknown whether package
    1571                 :             :                         // feerate was used when it was originally submitted.
    1572   [ +  -  +  -  :         398 :                         fees.pushKV("effective-feerate", ValueFromAmount(tx_result.m_effective_feerate.value().GetFeePerK()));
             +  -  +  - ]
    1573                 :         199 :                         UniValue effective_includes_res(UniValue::VARR);
    1574   [ +  -  +  + ]:         466 :                         for (const auto& wtxid : tx_result.m_wtxids_fee_calculations.value()) {
    1575   [ +  -  +  -  :         267 :                             effective_includes_res.push_back(wtxid.ToString());
                   +  - ]
    1576                 :             :                         }
    1577   [ +  -  +  - ]:         398 :                         fees.pushKV("effective-includes", std::move(effective_includes_res));
    1578                 :         199 :                     }
    1579   [ +  -  +  - ]:         576 :                     result_inner.pushKV("fees", std::move(fees));
    1580         [ +  + ]:         681 :                     for (const auto& ptx : it->second.m_replaced_transactions) {
    1581         [ +  - ]:         393 :                         replaced_txids.insert(ptx->GetHash());
    1582                 :             :                     }
    1583                 :         288 :                     break;
    1584                 :             :                 }
    1585   [ -  +  +  - ]:        1098 :                 tx_result_map.pushKV(wtxid_hex, std::move(result_inner));
    1586                 :         372 :             }
    1587   [ +  -  +  - ]:         226 :             rpc_result.pushKV("tx-results", std::move(tx_result_map));
    1588                 :         226 :             UniValue replaced_list(UniValue::VARR);
    1589   [ +  -  +  -  :         506 :             for (const auto& txid : replaced_txids) replaced_list.push_back(txid.ToString());
             +  -  +  + ]
    1590   [ +  -  +  - ]:         226 :             rpc_result.pushKV("replaced-transactions", std::move(replaced_list));
    1591                 :         226 :             return rpc_result;
    1592                 :         123 :         },
    1593   [ +  -  +  -  :       26550 :     };
          +  -  +  +  +  
             +  -  -  -  
                      - ]
    1594   [ +  -  +  -  :      106200 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  -  -  -  -  
             -  -  -  - ]
    1595                 :             : 
    1596                 :        1407 : void RegisterMempoolRPCCommands(CRPCTable& t)
    1597                 :             : {
    1598                 :        1407 :     static const CRPCCommand commands[]{
    1599         [ +  - ]:        2522 :         {"rawtransactions", &sendrawtransaction},
    1600         [ +  - ]:        2522 :         {"rawtransactions", &getprivatebroadcastinfo},
    1601         [ +  - ]:        2522 :         {"rawtransactions", &abortprivatebroadcast},
    1602         [ +  - ]:        2522 :         {"rawtransactions", &testmempoolaccept},
    1603         [ +  - ]:        2522 :         {"blockchain", &getmempoolancestors},
    1604         [ +  - ]:        2522 :         {"blockchain", &getmempooldescendants},
    1605         [ +  - ]:        2522 :         {"blockchain", &getmempoolentry},
    1606         [ +  - ]:        2522 :         {"blockchain", &getmempoolcluster},
    1607         [ +  - ]:        2522 :         {"blockchain", &gettxspendingprevout},
    1608         [ +  - ]:        2522 :         {"blockchain", &getmempoolinfo},
    1609         [ +  - ]:        2522 :         {"hidden", &getmempoolfeeratediagram},
    1610         [ +  - ]:        2522 :         {"blockchain", &getrawmempool},
    1611         [ +  - ]:        2522 :         {"blockchain", &importmempool},
    1612         [ +  - ]:        2522 :         {"blockchain", &savemempool},
    1613         [ +  - ]:        2522 :         {"hidden", &getorphantxs},
    1614         [ +  - ]:        2522 :         {"rawtransactions", &submitpackage},
    1615   [ +  +  +  -  :       21583 :     };
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  -  - ]
    1616         [ +  + ]:       23919 :     for (const auto& c : commands) {
    1617                 :       22512 :         t.appendCommand(c.name, &c);
    1618                 :             :     }
    1619                 :        1407 : }
        

Generated by: LCOV version 2.0-1