LCOV - code coverage report
Current view: top level - src/rpc - mempool.cpp (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 97.5 % 897 875
Test Date: 2025-12-04 05:03:34 Functions: 100.0 % 39 39
Branches: 51.5 % 3034 1561

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2010 Satoshi Nakamoto
       2                 :             : // Copyright (c) 2009-2022 The Bitcoin Core developers
       3                 :             : // Distributed under the MIT software license, see the accompanying
       4                 :             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5                 :             : 
       6                 :             : #include <rpc/blockchain.h>
       7                 :             : 
       8                 :             : #include <node/mempool_persist.h>
       9                 :             : 
      10                 :             : #include <chainparams.h>
      11                 :             : #include <consensus/validation.h>
      12                 :             : #include <core_io.h>
      13                 :             : #include <kernel/mempool_entry.h>
      14                 :             : #include <net_processing.h>
      15                 :             : #include <node/mempool_persist_args.h>
      16                 :             : #include <node/types.h>
      17                 :             : #include <policy/rbf.h>
      18                 :             : #include <policy/settings.h>
      19                 :             : #include <primitives/transaction.h>
      20                 :             : #include <rpc/server.h>
      21                 :             : #include <rpc/server_util.h>
      22                 :             : #include <rpc/util.h>
      23                 :             : #include <txmempool.h>
      24                 :             : #include <univalue.h>
      25                 :             : #include <util/fs.h>
      26                 :             : #include <util/moneystr.h>
      27                 :             : #include <util/strencodings.h>
      28                 :             : #include <util/time.h>
      29                 :             : #include <util/vector.h>
      30                 :             : 
      31                 :             : #include <string_view>
      32                 :             : #include <utility>
      33                 :             : 
      34                 :             : using node::DumpMempool;
      35                 :             : 
      36                 :             : using node::DEFAULT_MAX_BURN_AMOUNT;
      37                 :             : using node::DEFAULT_MAX_RAW_TX_FEE_RATE;
      38                 :             : using node::MempoolPath;
      39                 :             : using node::NodeContext;
      40                 :             : using node::TransactionError;
      41                 :             : using util::ToString;
      42                 :             : 
      43                 :       24838 : static RPCHelpMan sendrawtransaction()
      44                 :             : {
      45                 :       24838 :     return RPCHelpMan{
      46                 :       24838 :         "sendrawtransaction",
      47         [ +  - ]:       49676 :         "Submit a raw transaction (serialized, hex-encoded) to local node and network.\n"
      48                 :             :         "\nThe transaction will be sent unconditionally to all peers, so using sendrawtransaction\n"
      49                 :             :         "for manual rebroadcast may degrade privacy by leaking the transaction's origin, as\n"
      50                 :             :         "nodes will normally not rebroadcast non-wallet transactions already in their mempool.\n"
      51                 :             :         "\nA specific exception, RPC_TRANSACTION_ALREADY_IN_UTXO_SET, may throw if the transaction cannot be added to the mempool.\n"
      52                 :             :         "\nRelated RPCs: createrawtransaction, signrawtransactionwithkey\n",
      53                 :             :         {
      54   [ +  -  +  - ]:       49676 :             {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex string of the raw transaction"},
      55   [ +  -  +  -  :       49676 :             {"maxfeerate", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK())},
                   +  - ]
      56         [ +  - ]:       49676 :              "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT +
      57                 :       24838 :                  "/kvB.\nFee rates larger than 1BTC/kvB are rejected.\nSet to 0 to accept any fee rate."},
      58   [ +  -  +  -  :       49676 :             {"maxburnamount", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_BURN_AMOUNT)},
                   +  - ]
      59         [ +  - ]:       49676 :              "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"
      60                 :             :              "If burning funds through unspendable outputs is desired, increase this value.\n"
      61                 :       24838 :              "This check is based on heuristics and does not guarantee spendability of outputs.\n"},
      62                 :             :         },
      63         [ +  - ]:       49676 :         RPCResult{
      64   [ +  -  +  - ]:       49676 :             RPCResult::Type::STR_HEX, "", "The transaction hash in hex"
      65         [ +  - ]:       49676 :         },
      66                 :       24838 :         RPCExamples{
      67                 :             :             "\nCreate a transaction\n"
      68   [ +  -  +  -  :       49676 :             + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") +
             +  -  +  - ]
      69                 :       24838 :             "Sign the transaction, and get back the hex\n"
      70   [ +  -  +  -  :       99352 :             + HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
             +  -  +  - ]
      71                 :       24838 :             "\nSend the transaction (signed hex)\n"
      72   [ +  -  +  -  :       99352 :             + HelpExampleCli("sendrawtransaction", "\"signedhex\"") +
             +  -  +  - ]
      73                 :       24838 :             "\nAs a JSON-RPC call\n"
      74   [ +  -  +  -  :       99352 :             + HelpExampleRpc("sendrawtransaction", "\"signedhex\"")
             +  -  +  - ]
      75         [ +  - ]:       24838 :                 },
      76                 :       24838 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
      77                 :             :         {
      78         [ +  + ]:       22474 :             const CAmount max_burn_amount = request.params[2].isNull() ? 0 : AmountFromValue(request.params[2]);
      79                 :             : 
      80                 :       22474 :             CMutableTransaction mtx;
      81   [ +  -  +  -  :       22474 :             if (!DecodeHexTx(mtx, request.params[0].get_str())) {
             +  -  +  + ]
      82   [ +  -  +  - ]:           4 :                 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input.");
      83                 :             :             }
      84                 :             : 
      85         [ +  + ]:       79635 :             for (const auto& out : mtx.vout) {
      86   [ +  +  +  -  :       57167 :                 if((out.scriptPubKey.IsUnspendable() || !out.scriptPubKey.HasValidOps()) && out.nValue > max_burn_amount) {
             +  +  +  + ]
      87   [ +  -  +  - ]:           8 :                     throw JSONRPCTransactionError(TransactionError::MAX_BURN_EXCEEDED);
      88                 :             :                 }
      89                 :             :             }
      90                 :             : 
      91         [ +  - ]:       22468 :             CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
      92                 :             : 
      93   [ +  -  +  - ]:       22468 :             const CFeeRate max_raw_tx_fee_rate{ParseFeeRate(self.Arg<UniValue>("maxfeerate"))};
      94                 :             : 
      95         [ +  - ]:       22468 :             int64_t virtual_size = GetVirtualTransactionSize(*tx);
      96         [ +  - ]:       22468 :             CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size);
      97                 :             : 
      98         [ +  - ]:       22468 :             std::string err_string;
      99                 :       22468 :             AssertLockNotHeld(cs_main);
     100         [ +  - ]:       22468 :             NodeContext& node = EnsureAnyNodeContext(request.context);
     101   [ +  -  +  -  :       44936 :             const TransactionError err = BroadcastTransaction(node,
                   +  - ]
     102                 :             :                                                               tx,
     103                 :             :                                                               err_string,
     104                 :             :                                                               max_raw_tx_fee,
     105                 :             :                                                               node::TxBroadcast::MEMPOOL_AND_BROADCAST_TO_ALL,
     106                 :             :                                                               /*wait_callback=*/true);
     107         [ +  + ]:       22468 :             if (TransactionError::OK != err) {
     108         [ +  - ]:        4335 :                 throw JSONRPCTransactionError(err, err_string);
     109                 :             :             }
     110                 :             : 
     111   [ +  -  +  - ]:       36266 :             return tx->GetHash().GetHex();
     112         [ +  - ]:       63069 :         },
     113   [ +  -  +  -  :      173866 :     };
             +  +  -  - ]
     114   [ +  -  +  -  :      149028 : }
             +  -  -  - ]
     115                 :             : 
     116                 :        3863 : static RPCHelpMan testmempoolaccept()
     117                 :             : {
     118                 :        3863 :     return RPCHelpMan{
     119                 :        3863 :         "testmempoolaccept",
     120                 :             :         "Returns result of mempool acceptance tests indicating if raw transaction(s) (serialized, hex-encoded) would be accepted by mempool.\n"
     121                 :             :         "\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"
     122                 :             :         "\nIf one transaction fails, other transactions may not be fully validated (the 'allowed' key will be blank).\n"
     123   [ +  -  +  - ]:        7726 :         "\nThe maximum number of transactions allowed is " + ToString(MAX_PACKAGE_COUNT) + ".\n"
     124                 :             :         "\nThis checks if transactions violate the consensus or policy rules.\n"
     125                 :        3863 :         "\nSee sendrawtransaction call.\n",
     126                 :             :         {
     127   [ +  -  +  - ]:        7726 :             {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of hex strings of raw transactions.",
     128                 :             :                 {
     129   [ +  -  +  - ]:        7726 :                     {"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
     130                 :             :                 },
     131                 :             :             },
     132   [ +  -  +  -  :        7726 :             {"maxfeerate", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK())},
                   +  - ]
     133         [ +  - ]:        7726 :              "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT +
     134                 :        3863 :                  "/kvB.\nFee rates larger than 1BTC/kvB are rejected.\nSet to 0 to accept any fee rate."},
     135                 :             :         },
     136         [ +  - ]:        7726 :         RPCResult{
     137   [ +  -  +  - ]:        7726 :             RPCResult::Type::ARR, "", "The result of the mempool acceptance test for each raw transaction in the input array.\n"
     138                 :             :                                       "Returns results for each transaction in the same order they were passed in.\n"
     139                 :             :                                       "Transactions that cannot be fully validated due to failures in other transactions will not contain an 'allowed' result.\n",
     140                 :             :             {
     141   [ +  -  +  - ]:        7726 :                 {RPCResult::Type::OBJ, "", "",
     142                 :             :                 {
     143   [ +  -  +  - ]:        7726 :                     {RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
     144   [ +  -  +  - ]:        7726 :                     {RPCResult::Type::STR_HEX, "wtxid", "The transaction witness hash in hex"},
     145   [ +  -  +  - ]:        7726 :                     {RPCResult::Type::STR, "package-error", /*optional=*/true, "Package validation error, if any (only possible if rawtxs had more than 1 transaction)."},
     146   [ +  -  +  - ]:        7726 :                     {RPCResult::Type::BOOL, "allowed", /*optional=*/true, "Whether this tx would be accepted to the mempool and pass client-specified maxfeerate. "
     147                 :             :                                                        "If not present, the tx was not fully validated due to a failure in another tx in the list."},
     148   [ +  -  +  - ]:        7726 :                     {RPCResult::Type::NUM, "vsize", /*optional=*/true, "Virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted (only present when 'allowed' is true)"},
     149   [ +  -  +  - ]:        7726 :                     {RPCResult::Type::OBJ, "fees", /*optional=*/true, "Transaction fees (only present if 'allowed' is true)",
     150                 :             :                     {
     151   [ +  -  +  - ]:        7726 :                         {RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT},
     152   [ +  -  +  - ]:        7726 :                         {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."},
     153   [ +  -  +  - ]:        7726 :                         {RPCResult::Type::ARR, "effective-includes", /*optional=*/false, "transactions whose fees and vsizes are included in effective-feerate.",
     154   [ +  -  +  - ]:        7726 :                             {RPCResult{RPCResult::Type::STR_HEX, "", "transaction wtxid in hex"},
     155                 :             :                         }},
     156                 :             :                     }},
     157   [ +  -  +  - ]:        7726 :                     {RPCResult::Type::STR, "reject-reason", /*optional=*/true, "Rejection reason (only present when 'allowed' is false)"},
     158   [ +  -  +  - ]:        7726 :                     {RPCResult::Type::STR, "reject-details", /*optional=*/true, "Rejection details (only present when 'allowed' is false and rejection details exist)"},
     159                 :             :                 }},
     160                 :             :             }
     161   [ +  -  +  -  :      104301 :         },
          +  -  +  -  +  
          -  +  +  +  +  
          +  +  +  +  -  
          -  -  -  -  -  
                   -  - ]
     162                 :        3863 :         RPCExamples{
     163                 :             :             "\nCreate a transaction\n"
     164   [ +  -  +  -  :        7726 :             + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") +
             +  -  +  - ]
     165                 :        3863 :             "Sign the transaction, and get back the hex\n"
     166   [ +  -  +  -  :       15452 :             + HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
             +  -  +  - ]
     167                 :        3863 :             "\nTest acceptance of the transaction (signed hex)\n"
     168   [ +  -  +  -  :       15452 :             + HelpExampleCli("testmempoolaccept", R"('["signedhex"]')") +
             +  -  +  - ]
     169                 :        3863 :             "\nAs a JSON-RPC call\n"
     170   [ +  -  +  -  :       15452 :             + HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]")
             +  -  +  - ]
     171         [ +  - ]:        3863 :                 },
     172                 :        3863 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     173                 :             :         {
     174                 :        1499 :             const UniValue raw_transactions = request.params[0].get_array();
     175   [ -  +  +  +  :        1499 :             if (raw_transactions.size() < 1 || raw_transactions.size() > MAX_PACKAGE_COUNT) {
                   +  + ]
     176                 :           2 :                 throw JSONRPCError(RPC_INVALID_PARAMETER,
     177   [ +  -  +  -  :           6 :                                    "Array must contain between 1 and " + ToString(MAX_PACKAGE_COUNT) + " transactions.");
                   +  - ]
     178                 :             :             }
     179                 :             : 
     180   [ +  -  +  + ]:        1497 :             const CFeeRate max_raw_tx_fee_rate{ParseFeeRate(self.Arg<UniValue>("maxfeerate"))};
     181                 :             : 
     182                 :        1495 :             std::vector<CTransactionRef> txns;
     183   [ -  +  +  - ]:        1495 :             txns.reserve(raw_transactions.size());
     184   [ +  -  +  + ]:        3574 :             for (const auto& rawtx : raw_transactions.getValues()) {
     185         [ +  - ]:        2080 :                 CMutableTransaction mtx;
     186   [ +  -  +  -  :        2080 :                 if (!DecodeHexTx(mtx, rawtx.get_str())) {
                   +  + ]
     187                 :           1 :                     throw JSONRPCError(RPC_DESERIALIZATION_ERROR,
     188   [ +  -  +  -  :           3 :                                        "TX decode failed: " + rawtx.get_str() + " Make sure the tx has at least one input.");
                   +  - ]
     189                 :             :                 }
     190   [ +  -  +  - ]:        6237 :                 txns.emplace_back(MakeTransactionRef(std::move(mtx)));
     191                 :        2080 :             }
     192                 :             : 
     193         [ +  - ]:        1494 :             NodeContext& node = EnsureAnyNodeContext(request.context);
     194         [ +  - ]:        1494 :             CTxMemPool& mempool = EnsureMemPool(node);
     195         [ +  - ]:        1494 :             ChainstateManager& chainman = EnsureChainman(node);
     196         [ +  - ]:        1494 :             Chainstate& chainstate = chainman.ActiveChainstate();
     197                 :        2988 :             const PackageMempoolAcceptResult package_result = [&] {
     198                 :        1494 :                 LOCK(::cs_main);
     199   [ -  +  +  +  :        1494 :                 if (txns.size() > 1) return ProcessNewPackage(chainstate, mempool, txns, /*test_accept=*/true, /*client_maxfeerate=*/{});
                   +  - ]
     200         [ +  - ]:        1418 :                 return PackageMempoolAcceptResult(txns[0]->GetWitnessHash(),
     201   [ +  -  +  - ]:        1418 :                                                   chainman.ProcessTransaction(txns[0], /*test_accept=*/true));
     202         [ +  - ]:        2988 :             }();
     203                 :             : 
     204                 :        1494 :             UniValue rpc_result(UniValue::VARR);
     205                 :             :             // We will check transaction fees while we iterate through txns in order. If any transaction fee
     206                 :             :             // exceeds maxfeerate, we will leave the rest of the validation results blank, because it
     207                 :             :             // doesn't make sense to return a validation result for a transaction if its ancestor(s) would
     208                 :             :             // not be submitted.
     209                 :        1494 :             bool exit_early{false};
     210         [ +  + ]:        3573 :             for (const auto& tx : txns) {
     211                 :        2079 :                 UniValue result_inner(UniValue::VOBJ);
     212   [ +  -  +  -  :        4158 :                 result_inner.pushKV("txid", tx->GetHash().GetHex());
             +  -  +  - ]
     213   [ +  -  +  -  :        4158 :                 result_inner.pushKV("wtxid", tx->GetWitnessHash().GetHex());
             +  -  +  - ]
     214         [ +  + ]:        2079 :                 if (package_result.m_state.GetResult() == PackageValidationResult::PCKG_POLICY) {
     215   [ +  -  +  -  :         198 :                     result_inner.pushKV("package-error", package_result.m_state.ToString());
             +  -  +  - ]
     216                 :             :                 }
     217                 :        2079 :                 auto it = package_result.m_tx_results.find(tx->GetWitnessHash());
     218   [ +  +  +  + ]:        2079 :                 if (exit_early || it == package_result.m_tx_results.end()) {
     219                 :             :                     // Validation unfinished. Just return the txid and wtxid.
     220         [ +  - ]:         139 :                     rpc_result.push_back(std::move(result_inner));
     221                 :         139 :                     continue;
     222                 :             :                 }
     223         [ +  - ]:        1940 :                 const auto& tx_result = it->second;
     224                 :             :                 // Package testmempoolaccept doesn't allow transactions to already be in the mempool.
     225         [ +  - ]:        1940 :                 CHECK_NONFATAL(tx_result.m_result_type != MempoolAcceptResult::ResultType::MEMPOOL_ENTRY);
     226         [ +  + ]:        1940 :                 if (tx_result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
     227         [ +  - ]:        1691 :                     const CAmount fee = tx_result.m_base_fees.value();
     228                 :             :                     // Check that fee does not exceed maximum fee
     229         [ +  - ]:        1691 :                     const int64_t virtual_size = tx_result.m_vsize.value();
     230         [ +  - ]:        1691 :                     const CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size);
     231         [ +  + ]:        1691 :                     if (max_raw_tx_fee && fee > max_raw_tx_fee) {
     232   [ +  -  +  -  :           8 :                         result_inner.pushKV("allowed", false);
                   +  - ]
     233   [ +  -  +  -  :           4 :                         result_inner.pushKV("reject-reason", "max-fee-exceeded");
                   +  - ]
     234                 :           4 :                         exit_early = true;
     235                 :             :                     } else {
     236                 :             :                         // Only return the fee and vsize if the transaction would pass ATMP.
     237                 :             :                         // These can be used to calculate the feerate.
     238   [ +  -  +  -  :        3374 :                         result_inner.pushKV("allowed", true);
                   +  - ]
     239   [ +  -  +  -  :        3374 :                         result_inner.pushKV("vsize", virtual_size);
                   +  - ]
     240                 :        1687 :                         UniValue fees(UniValue::VOBJ);
     241   [ +  -  +  -  :        3374 :                         fees.pushKV("base", ValueFromAmount(fee));
                   +  - ]
     242   [ +  -  +  -  :        3374 :                         fees.pushKV("effective-feerate", ValueFromAmount(tx_result.m_effective_feerate.value().GetFeePerK()));
             +  -  +  - ]
     243                 :        1687 :                         UniValue effective_includes_res(UniValue::VARR);
     244   [ +  -  +  + ]:        3374 :                         for (const auto& wtxid : tx_result.m_wtxids_fee_calculations.value()) {
     245   [ +  -  +  -  :        1687 :                             effective_includes_res.push_back(wtxid.ToString());
                   +  - ]
     246                 :             :                         }
     247   [ +  -  +  - ]:        3374 :                         fees.pushKV("effective-includes", std::move(effective_includes_res));
     248   [ +  -  +  - ]:        3374 :                         result_inner.pushKV("fees", std::move(fees));
     249                 :        1687 :                     }
     250                 :             :                 } else {
     251   [ +  -  +  -  :         498 :                     result_inner.pushKV("allowed", false);
                   +  - ]
     252         [ +  - ]:         249 :                     const TxValidationState state = tx_result.m_state;
     253         [ +  + ]:         249 :                     if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
     254   [ +  -  +  -  :         232 :                         result_inner.pushKV("reject-reason", "missing-inputs");
                   +  - ]
     255                 :             :                     } else {
     256   [ -  +  +  -  :         399 :                         result_inner.pushKV("reject-reason", state.GetRejectReason());
             +  -  +  - ]
     257   [ +  -  +  -  :         266 :                         result_inner.pushKV("reject-details", state.ToString());
             +  -  +  - ]
     258                 :             :                     }
     259                 :         249 :                 }
     260         [ +  - ]:        1940 :                 rpc_result.push_back(std::move(result_inner));
     261                 :        2079 :             }
     262                 :        1494 :             return rpc_result;
     263                 :        1500 :         },
     264   [ +  -  +  -  :       34767 :     };
          +  -  +  +  +  
             +  -  -  -  
                      - ]
     265   [ +  -  +  -  :       73397 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  -  
             -  -  -  - ]
     266                 :             : 
     267                 :        3505 : static std::vector<RPCResult> ClusterDescription()
     268                 :             : {
     269                 :        3505 :     return {
     270   [ +  -  +  - ]:        7010 :         RPCResult{RPCResult::Type::NUM, "clusterweight", "total sigops-adjusted weight (as defined in BIP 141 and modified by '-bytespersigop')"},
     271   [ +  -  +  - ]:        7010 :         RPCResult{RPCResult::Type::NUM, "txcount", "number of transactions"},
     272   [ +  -  +  - ]:        7010 :         RPCResult{RPCResult::Type::ARR, "chunks", "chunks in this cluster (in mining order)",
     273   [ +  -  +  - ]:        7010 :             {RPCResult{RPCResult::Type::OBJ, "chunk", "",
     274                 :             :                 {
     275   [ +  -  +  - ]:        7010 :                     RPCResult{RPCResult::Type::NUM, "chunkfee", "fees of the transactions in this chunk"},
     276   [ +  -  +  - ]:        7010 :                     RPCResult{RPCResult::Type::NUM, "chunkweight", "sigops-adjusted weight of all transactions in this chunk"},
     277   [ +  -  +  - ]:        7010 :                     RPCResult{RPCResult::Type::ARR, "txs", "transactions in this chunk in mining order",
     278   [ +  -  +  -  :       14020 :                         {RPCResult{RPCResult::Type::STR_HEX, "txid", "transaction id"}}},
          +  -  +  +  -  
                      - ]
     279                 :             :                 }
     280   [ +  -  +  +  :       17525 :             }}
                   -  - ]
     281   [ +  -  +  +  :       10515 :         }
                   -  - ]
     282   [ +  -  +  +  :       21030 :     };
                   -  - ]
     283   [ +  -  +  -  :       28040 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  -  -  
                      - ]
     284                 :             : 
     285                 :       27871 : static std::vector<RPCResult> MempoolEntryDescription()
     286                 :             : {
     287                 :       27871 :     return {
     288   [ +  -  +  - ]:       55742 :         RPCResult{RPCResult::Type::NUM, "vsize", "virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted."},
     289   [ +  -  +  - ]:       55742 :         RPCResult{RPCResult::Type::NUM, "weight", "transaction weight as defined in BIP 141."},
     290   [ +  -  +  - ]:       55742 :         RPCResult{RPCResult::Type::NUM_TIME, "time", "local time transaction entered pool in seconds since 1 Jan 1970 GMT"},
     291   [ +  -  +  - ]:       55742 :         RPCResult{RPCResult::Type::NUM, "height", "block height when transaction entered pool"},
     292   [ +  -  +  - ]:       55742 :         RPCResult{RPCResult::Type::NUM, "descendantcount", "number of in-mempool descendant transactions (including this one)"},
     293   [ +  -  +  - ]:       55742 :         RPCResult{RPCResult::Type::NUM, "descendantsize", "virtual transaction size of in-mempool descendants (including this one)"},
     294   [ +  -  +  - ]:       55742 :         RPCResult{RPCResult::Type::NUM, "ancestorcount", "number of in-mempool ancestor transactions (including this one)"},
     295   [ +  -  +  - ]:       55742 :         RPCResult{RPCResult::Type::NUM, "ancestorsize", "virtual transaction size of in-mempool ancestors (including this one)"},
     296   [ +  -  +  - ]:       55742 :         RPCResult{RPCResult::Type::NUM, "chunkweight", "sigops-adjusted weight (as defined in BIP 141 and modified by '-bytespersigop') of this transaction's chunk"},
     297   [ +  -  +  - ]:       55742 :         RPCResult{RPCResult::Type::STR_HEX, "wtxid", "hash of serialized transaction, including witness data"},
     298   [ +  -  +  - ]:       55742 :         RPCResult{RPCResult::Type::OBJ, "fees", "",
     299                 :             :             {
     300   [ +  -  +  - ]:       55742 :                 RPCResult{RPCResult::Type::STR_AMOUNT, "base", "transaction fee, denominated in " + CURRENCY_UNIT},
     301   [ +  -  +  - ]:       55742 :                 RPCResult{RPCResult::Type::STR_AMOUNT, "modified", "transaction fee with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT},
     302   [ +  -  +  - ]:       55742 :                 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},
     303   [ +  -  +  - ]:       55742 :                 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},
     304   [ +  -  +  - ]:       55742 :                 RPCResult{RPCResult::Type::STR_AMOUNT, "chunk", "transaction fees of chunk, denominated in " + CURRENCY_UNIT},
     305   [ +  -  +  +  :      195097 :             }},
                   -  - ]
     306   [ +  -  +  - ]:       55742 :         RPCResult{RPCResult::Type::ARR, "depends", "unconfirmed transactions used as inputs for this transaction",
     307   [ +  -  +  -  :      111484 :             {RPCResult{RPCResult::Type::STR_HEX, "transactionid", "parent transaction id"}}},
          +  -  +  +  -  
                      - ]
     308   [ +  -  +  - ]:       55742 :         RPCResult{RPCResult::Type::ARR, "spentby", "unconfirmed transactions spending outputs from this transaction",
     309   [ +  -  +  -  :      111484 :             {RPCResult{RPCResult::Type::STR_HEX, "transactionid", "child transaction id"}}},
          +  -  +  +  -  
                      - ]
     310   [ +  -  +  - ]:       55742 :         RPCResult{RPCResult::Type::BOOL, "bip125-replaceable", "Whether this transaction signals BIP125 replaceability or has an unconfirmed ancestor signaling BIP125 replaceability. (DEPRECATED)\n"},
     311   [ +  -  +  - ]:       55742 :         RPCResult{RPCResult::Type::BOOL, "unbroadcast", "Whether this transaction is currently unbroadcast (initial broadcast not yet acknowledged by any peers)"},
     312   [ +  -  +  +  :      501678 :     };
                   -  - ]
     313   [ +  -  +  -  :      613162 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             -  -  -  - ]
     314                 :             : 
     315                 :       25886 : void AppendChunkInfo(UniValue& all_chunks, FeePerWeight chunk_feerate, std::vector<const CTxMemPoolEntry *> chunk_txs)
     316                 :             : {
     317                 :       25886 :     UniValue chunk(UniValue::VOBJ);
     318   [ +  -  +  -  :       51772 :     chunk.pushKV("chunkfee", ValueFromAmount((int)chunk_feerate.fee));
                   +  - ]
     319   [ +  -  +  -  :       51772 :     chunk.pushKV("chunkweight", chunk_feerate.size);
                   +  - ]
     320                 :       25886 :     UniValue chunk_txids(UniValue::VARR);
     321         [ +  + ]:       51780 :     for (const auto& chunk_tx : chunk_txs) {
     322   [ +  -  +  -  :       25894 :         chunk_txids.push_back(chunk_tx->GetTx().GetHash().ToString());
                   +  - ]
     323                 :             :     }
     324   [ +  -  +  - ]:       51772 :     chunk.pushKV("txs", std::move(chunk_txids));
     325         [ +  - ]:       25886 :     all_chunks.push_back(std::move(chunk));
     326                 :       25886 : }
     327                 :             : 
     328                 :        1141 : static void clusterToJSON(const CTxMemPool& pool, UniValue& info, std::vector<const CTxMemPoolEntry *> cluster) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
     329                 :             : {
     330                 :        1141 :     AssertLockHeld(pool.cs);
     331                 :        1141 :     int total_weight{0};
     332         [ +  + ]:       27035 :     for (const auto& tx : cluster) {
     333                 :       25894 :         total_weight += tx->GetAdjustedWeight();
     334                 :             :     }
     335   [ +  -  +  - ]:        2282 :     info.pushKV("clusterweight", total_weight);
     336   [ -  +  +  -  :        2282 :     info.pushKV("txcount", (int)cluster.size());
                   +  - ]
     337                 :             : 
     338                 :             :     // Output the cluster by chunk. This isn't handed to us by the mempool, but
     339                 :             :     // we can calculate it by looking at the chunk feerates of each transaction
     340                 :             :     // in the cluster.
     341                 :        1141 :     FeePerWeight current_chunk_feerate = pool.GetMainChunkFeerate(*cluster[0]);
     342                 :        1141 :     std::vector<const CTxMemPoolEntry *> current_chunk;
     343   [ -  +  +  - ]:        1141 :     current_chunk.reserve(cluster.size());
     344                 :             : 
     345                 :        1141 :     UniValue all_chunks(UniValue::VARR);
     346         [ +  + ]:       27035 :     for (const auto& tx : cluster) {
     347         [ +  + ]:       25894 :         if (current_chunk_feerate.size == 0) {
     348                 :             :             // We've iterated all the transactions in the previous chunk; so
     349                 :             :             // append it to the output.
     350   [ +  -  +  - ]:       24745 :             AppendChunkInfo(all_chunks, pool.GetMainChunkFeerate(*current_chunk[0]), current_chunk);
     351         [ +  - ]:       24745 :             current_chunk.clear();
     352                 :       24745 :             current_chunk_feerate = pool.GetMainChunkFeerate(*tx);
     353                 :             :         }
     354         [ +  - ]:       25894 :         current_chunk.push_back(tx);
     355         [ +  - ]:       25894 :         current_chunk_feerate.size -= tx->GetAdjustedWeight();
     356                 :             :     }
     357   [ +  -  +  - ]:        1141 :     AppendChunkInfo(all_chunks, pool.GetMainChunkFeerate(*current_chunk[0]), current_chunk);
     358         [ +  - ]:        1141 :     current_chunk.clear();
     359   [ +  -  +  - ]:        2282 :     info.pushKV("chunks", std::move(all_chunks));
     360                 :        1141 : }
     361                 :             : 
     362                 :        8059 : static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPoolEntry& e) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
     363                 :             : {
     364                 :        8059 :     AssertLockHeld(pool.cs);
     365                 :             : 
     366                 :        8059 :     auto [ancestor_count, ancestor_size, ancestor_fees] = pool.CalculateAncestorData(e);
     367                 :        8059 :     auto [descendant_count, descendant_size, descendant_fees] = pool.CalculateDescendantData(e);
     368                 :             : 
     369   [ +  -  +  - ]:       16118 :     info.pushKV("vsize", (int)e.GetTxSize());
     370   [ +  -  +  - ]:       16118 :     info.pushKV("weight", (int)e.GetTxWeight());
     371   [ +  -  +  - ]:       16118 :     info.pushKV("time", count_seconds(e.GetTime()));
     372   [ +  -  +  - ]:       16118 :     info.pushKV("height", (int)e.GetHeight());
     373   [ +  -  +  - ]:       16118 :     info.pushKV("descendantcount", descendant_count);
     374   [ +  -  +  - ]:       16118 :     info.pushKV("descendantsize", descendant_size);
     375   [ +  -  +  - ]:       16118 :     info.pushKV("ancestorcount", ancestor_count);
     376   [ +  -  +  - ]:       16118 :     info.pushKV("ancestorsize", ancestor_size);
     377   [ +  -  +  -  :       16118 :     info.pushKV("wtxid", e.GetTx().GetWitnessHash().ToString());
                   +  - ]
     378                 :        8059 :     auto feerate = pool.GetMainChunkFeerate(e);
     379   [ +  -  +  - ]:       16118 :     info.pushKV("chunkweight", feerate.size);
     380                 :             : 
     381                 :        8059 :     UniValue fees(UniValue::VOBJ);
     382   [ +  -  +  -  :       16118 :     fees.pushKV("base", ValueFromAmount(e.GetFee()));
                   +  - ]
     383   [ +  -  +  -  :       16118 :     fees.pushKV("modified", ValueFromAmount(e.GetModifiedFee()));
                   +  - ]
     384   [ +  -  +  -  :       16118 :     fees.pushKV("ancestor", ValueFromAmount(ancestor_fees));
                   +  - ]
     385   [ +  -  +  -  :       16118 :     fees.pushKV("descendant", ValueFromAmount(descendant_fees));
                   +  - ]
     386   [ +  -  +  -  :       16118 :     fees.pushKV("chunk", ValueFromAmount((int)feerate.fee));
                   +  - ]
     387   [ +  -  +  - ]:       16118 :     info.pushKV("fees", std::move(fees));
     388                 :             : 
     389                 :        8059 :     const CTransaction& tx = e.GetTx();
     390                 :        8059 :     std::set<std::string> setDepends;
     391         [ +  + ]:       18796 :     for (const CTxIn& txin : tx.vin)
     392                 :             :     {
     393   [ +  -  +  + ]:       10737 :         if (pool.exists(txin.prevout.hash))
     394   [ +  -  +  - ]:       14158 :             setDepends.insert(txin.prevout.hash.ToString());
     395                 :             :     }
     396                 :             : 
     397                 :        8059 :     UniValue depends(UniValue::VARR);
     398         [ +  + ]:       15138 :     for (const std::string& dep : setDepends)
     399                 :             :     {
     400   [ +  -  +  - ]:        7079 :         depends.push_back(dep);
     401                 :             :     }
     402                 :             : 
     403   [ +  -  +  - ]:       16118 :     info.pushKV("depends", std::move(depends));
     404                 :             : 
     405                 :        8059 :     UniValue spent(UniValue::VARR);
     406   [ +  -  +  -  :       15163 :     for (const CTxMemPoolEntry& child : pool.GetChildren(e)) {
                   +  + ]
     407   [ +  -  +  -  :        7104 :         spent.push_back(child.GetTx().GetHash().ToString());
                   +  - ]
     408                 :           0 :     }
     409                 :             : 
     410   [ +  -  +  - ]:       16118 :     info.pushKV("spentby", std::move(spent));
     411                 :             : 
     412                 :             :     // Add opt-in RBF status
     413                 :        8059 :     bool rbfStatus = false;
     414         [ +  - ]:        8059 :     RBFTransactionState rbfState = IsRBFOptIn(tx, pool);
     415         [ -  + ]:        8059 :     if (rbfState == RBFTransactionState::UNKNOWN) {
     416   [ #  #  #  # ]:           0 :         throw JSONRPCError(RPC_MISC_ERROR, "Transaction is not in mempool");
     417         [ +  + ]:        8059 :     } else if (rbfState == RBFTransactionState::REPLACEABLE_BIP125) {
     418                 :        7433 :         rbfStatus = true;
     419                 :             :     }
     420                 :             : 
     421   [ +  -  +  -  :       16118 :     info.pushKV("bip125-replaceable", rbfStatus);
                   +  - ]
     422   [ +  -  +  -  :       16118 :     info.pushKV("unbroadcast", pool.IsUnbroadcastTx(tx.GetHash()));
                   +  - ]
     423                 :        8059 : }
     424                 :             : 
     425                 :        7515 : UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose, bool include_mempool_sequence)
     426                 :             : {
     427         [ +  + ]:        7515 :     if (verbose) {
     428         [ +  + ]:        1048 :         if (include_mempool_sequence) {
     429   [ +  -  +  - ]:           2 :             throw JSONRPCError(RPC_INVALID_PARAMETER, "Verbose results cannot contain mempool sequence values.");
     430                 :             :         }
     431                 :        1047 :         LOCK(pool.cs);
     432                 :        1047 :         UniValue o(UniValue::VOBJ);
     433   [ +  -  +  + ]:        4178 :         for (const CTxMemPoolEntry& e : pool.entryAll()) {
     434                 :        3131 :             UniValue info(UniValue::VOBJ);
     435         [ +  - ]:        3131 :             entryToJSON(pool, info, e);
     436                 :             :             // Mempool has unique entries so there is no advantage in using
     437                 :             :             // UniValue::pushKV, which checks if the key already exists in O(N).
     438                 :             :             // UniValue::pushKVEnd is used instead which currently is O(1).
     439   [ +  -  +  - ]:        6262 :             o.pushKVEnd(e.GetTx().GetHash().ToString(), std::move(info));
     440                 :        3131 :         }
     441         [ +  - ]:        1047 :         return o;
     442                 :        1047 :     } else {
     443                 :        6467 :         UniValue a(UniValue::VARR);
     444                 :        6467 :         uint64_t mempool_sequence;
     445                 :        6467 :         {
     446         [ +  - ]:        6467 :             LOCK(pool.cs);
     447   [ +  -  +  -  :      247293 :             for (const CTxMemPoolEntry& e : pool.entryAll()) {
                   +  + ]
     448   [ +  -  +  -  :      240826 :                 a.push_back(e.GetTx().GetHash().ToString());
                   +  - ]
     449                 :             :             }
     450         [ +  - ]:        6467 :             mempool_sequence = pool.GetSequence();
     451                 :           0 :         }
     452         [ +  + ]:        6467 :         if (!include_mempool_sequence) {
     453                 :        6446 :             return a;
     454                 :             :         } else {
     455                 :          21 :             UniValue o(UniValue::VOBJ);
     456   [ +  -  +  - ]:          42 :             o.pushKV("txids", std::move(a));
     457   [ +  -  +  -  :          42 :             o.pushKV("mempool_sequence", mempool_sequence);
                   +  - ]
     458                 :          21 :             return o;
     459                 :          21 :         }
     460                 :        6467 :     }
     461                 :             : }
     462                 :             : 
     463                 :        2359 : static RPCHelpMan getmempoolfeeratediagram()
     464                 :             : {
     465                 :        2359 :     return RPCHelpMan{"getmempoolfeeratediagram",
     466         [ +  - ]:        4718 :         "Returns the feerate diagram for the whole mempool.",
     467                 :             :         {},
     468                 :             :         {
     469                 :           0 :             RPCResult{"mempool chunks",
     470   [ +  -  +  - ]:        4718 :                 RPCResult::Type::ARR, "", "",
     471                 :             :                 {
     472                 :             :                     {
     473   [ +  -  +  - ]:        4718 :                         RPCResult::Type::OBJ, "", "",
     474                 :             :                         {
     475   [ +  -  +  - ]:        4718 :                             {RPCResult::Type::NUM, "weight", "cumulative sigops-adjusted weight"},
     476   [ +  -  +  - ]:        4718 :                             {RPCResult::Type::NUM, "fee", "cumulative fee"}
     477                 :             :                         }
     478                 :             :                     }
     479                 :             :                 }
     480   [ +  -  +  -  :       16513 :             }
          +  +  +  +  -  
                -  -  - ]
     481                 :             :         },
     482                 :        2359 :         RPCExamples{
     483   [ +  -  +  -  :        4718 :             HelpExampleCli("getmempoolfeeratediagram", "")
                   +  - ]
     484   [ +  -  +  -  :        9436 :             + HelpExampleRpc("getmempoolfeeratediagram", "")
                   +  - ]
     485         [ +  - ]:        2359 :         },
     486                 :        2359 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     487                 :             :         {
     488                 :           5 :             const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
     489                 :           5 :             LOCK(mempool.cs);
     490                 :             : 
     491                 :           5 :             UniValue result(UniValue::VARR);
     492                 :             : 
     493         [ +  - ]:           5 :             auto diagram = mempool.GetFeerateDiagram();
     494                 :             : 
     495         [ +  + ]:         136 :             for (auto f : diagram) {
     496                 :         131 :                 UniValue o(UniValue::VOBJ);
     497   [ +  -  +  -  :         262 :                 o.pushKV("weight", f.size);
                   +  - ]
     498   [ +  -  +  -  :         262 :                 o.pushKV("fee", ValueFromAmount(f.fee));
                   +  - ]
     499   [ +  -  +  - ]:         131 :                 result.push_back(o);
     500                 :         131 :             }
     501                 :           5 :             return result;
     502         [ +  - ]:          10 :         }
     503   [ +  -  +  -  :       18872 :     };
          +  -  +  -  +  
                +  -  - ]
     504   [ +  -  +  -  :        9436 : }
          +  -  +  -  -  
                      - ]
     505                 :             : 
     506                 :        9874 : static RPCHelpMan getrawmempool()
     507                 :             : {
     508                 :        9874 :     return RPCHelpMan{
     509                 :        9874 :         "getrawmempool",
     510         [ +  - ]:       19748 :         "Returns all transaction ids in memory pool as a json array of string transaction ids.\n"
     511                 :             :         "\nHint: use getmempoolentry to fetch a specific transaction from the mempool.\n",
     512                 :             :         {
     513   [ +  -  +  -  :       29622 :             {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "True for a json object, false for array of transaction ids"},
                   +  - ]
     514   [ +  -  +  -  :       29622 :             {"mempool_sequence", RPCArg::Type::BOOL, RPCArg::Default{false}, "If verbose=false, returns a json object with transaction list and mempool sequence number attached."},
                   +  - ]
     515                 :             :         },
     516                 :             :         {
     517         [ +  - ]:        9874 :             RPCResult{"for verbose = false",
     518   [ +  -  +  - ]:       19748 :                 RPCResult::Type::ARR, "", "",
     519                 :             :                 {
     520   [ +  -  +  - ]:       19748 :                     {RPCResult::Type::STR_HEX, "", "The transaction id"},
     521   [ +  -  +  +  :       29622 :                 }},
                   -  - ]
     522         [ +  - ]:       19748 :             RPCResult{"for verbose = true",
     523   [ +  -  +  - ]:       19748 :                 RPCResult::Type::OBJ_DYN, "", "",
     524                 :             :                 {
     525   [ +  -  +  -  :       19748 :                     {RPCResult::Type::OBJ, "transactionid", "", MempoolEntryDescription()},
                   +  - ]
     526   [ +  -  +  +  :       29622 :                 }},
                   -  - ]
     527         [ +  - ]:       19748 :             RPCResult{"for verbose = false and mempool_sequence = true",
     528   [ +  -  +  - ]:       19748 :                 RPCResult::Type::OBJ, "", "",
     529                 :             :                 {
     530   [ +  -  +  - ]:       19748 :                     {RPCResult::Type::ARR, "txids", "",
     531                 :             :                     {
     532   [ +  -  +  - ]:       19748 :                         {RPCResult::Type::STR_HEX, "", "The transaction id"},
     533                 :             :                     }},
     534   [ +  -  +  - ]:       19748 :                     {RPCResult::Type::NUM, "mempool_sequence", "The mempool sequence value."},
     535   [ +  -  +  -  :       69118 :                 }},
          +  +  +  +  -  
                -  -  - ]
     536                 :             :         },
     537                 :        9874 :         RPCExamples{
     538   [ +  -  +  -  :       19748 :             HelpExampleCli("getrawmempool", "true")
                   +  - ]
     539   [ +  -  +  -  :       39496 :             + HelpExampleRpc("getrawmempool", "true")
                   +  - ]
     540         [ +  - ]:        9874 :         },
     541                 :        9874 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     542                 :             : {
     543                 :        7511 :     bool fVerbose = false;
     544         [ +  + ]:        7511 :     if (!request.params[0].isNull())
     545                 :        1103 :         fVerbose = request.params[0].get_bool();
     546                 :             : 
     547                 :        7511 :     bool include_mempool_sequence = false;
     548         [ +  + ]:        7511 :     if (!request.params[1].isNull()) {
     549                 :          22 :         include_mempool_sequence = request.params[1].get_bool();
     550                 :             :     }
     551                 :             : 
     552                 :        7511 :     return MempoolToJSON(EnsureAnyMemPool(request.context), fVerbose, include_mempool_sequence);
     553                 :             : },
     554   [ +  -  +  -  :      118488 :     };
          +  -  +  -  +  
          +  +  +  -  -  
                   -  - ]
     555   [ +  -  +  -  :      118488 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  -  -  -  -  
                   -  - ]
     556                 :             : 
     557                 :        2976 : static RPCHelpMan getmempoolancestors()
     558                 :             : {
     559                 :        2976 :     return RPCHelpMan{
     560                 :        2976 :         "getmempoolancestors",
     561         [ +  - ]:        5952 :         "If txid is in the mempool, returns all in-mempool ancestors.\n",
     562                 :             :         {
     563   [ +  -  +  - ]:        5952 :             {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"},
     564   [ +  -  +  -  :        8928 :             {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "True for a json object, false for array of transaction ids"},
                   +  - ]
     565                 :             :         },
     566                 :             :         {
     567         [ +  - ]:        2976 :             RPCResult{"for verbose = false",
     568   [ +  -  +  - ]:        5952 :                 RPCResult::Type::ARR, "", "",
     569   [ +  -  +  -  :       11904 :                 {{RPCResult::Type::STR_HEX, "", "The transaction id of an in-mempool ancestor transaction"}}},
          +  -  +  +  -  
                      - ]
     570         [ +  - ]:        5952 :             RPCResult{"for verbose = true",
     571   [ +  -  +  - ]:        5952 :                 RPCResult::Type::OBJ_DYN, "", "",
     572                 :             :                 {
     573   [ +  -  +  -  :        5952 :                     {RPCResult::Type::OBJ, "transactionid", "", MempoolEntryDescription()},
                   +  - ]
     574   [ +  -  +  +  :        8928 :                 }},
                   -  - ]
     575                 :             :         },
     576                 :        2976 :         RPCExamples{
     577   [ +  -  +  -  :        5952 :             HelpExampleCli("getmempoolancestors", "\"mytxid\"")
                   +  - ]
     578   [ +  -  +  -  :       11904 :             + HelpExampleRpc("getmempoolancestors", "\"mytxid\"")
                   +  - ]
     579         [ +  - ]:        2976 :         },
     580                 :        2976 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     581                 :             : {
     582                 :         613 :     bool fVerbose = false;
     583         [ +  + ]:         613 :     if (!request.params[1].isNull())
     584                 :          65 :         fVerbose = request.params[1].get_bool();
     585                 :             : 
     586                 :         613 :     auto txid{Txid::FromUint256(ParseHashV(request.params[0], "txid"))};
     587                 :             : 
     588                 :         613 :     const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
     589                 :         613 :     LOCK(mempool.cs);
     590                 :             : 
     591         [ +  - ]:         613 :     const auto entry{mempool.GetEntry(txid)};
     592         [ -  + ]:         613 :     if (entry == nullptr) {
     593   [ #  #  #  # ]:           0 :         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool");
     594                 :             :     }
     595                 :             : 
     596         [ +  - ]:         613 :     auto ancestors{mempool.CalculateMemPoolAncestors(*entry)};
     597                 :             : 
     598         [ +  + ]:         613 :     if (!fVerbose) {
     599                 :         548 :         UniValue o(UniValue::VARR);
     600         [ +  + ]:       11954 :         for (CTxMemPool::txiter ancestorIt : ancestors) {
     601   [ +  -  +  -  :       11406 :             o.push_back(ancestorIt->GetTx().GetHash().ToString());
                   +  - ]
     602                 :             :         }
     603                 :             :         return o;
     604                 :           0 :     } else {
     605                 :          65 :         UniValue o(UniValue::VOBJ);
     606         [ +  + ]:        2144 :         for (CTxMemPool::txiter ancestorIt : ancestors) {
     607                 :        2079 :             const CTxMemPoolEntry &e = *ancestorIt;
     608                 :        2079 :             UniValue info(UniValue::VOBJ);
     609         [ +  - ]:        2079 :             entryToJSON(mempool, info, e);
     610   [ +  -  +  - ]:        4158 :             o.pushKV(e.GetTx().GetHash().ToString(), std::move(info));
     611                 :        2079 :         }
     612                 :          65 :         return o;
     613                 :          65 :     }
     614         [ +  - ]:        1226 : },
     615   [ +  -  +  -  :       32736 :     };
          +  -  +  -  +  
          +  +  +  -  -  
                   -  - ]
     616   [ +  -  +  -  :       23808 : }
          +  -  +  -  +  
          -  +  -  -  -  
                   -  - ]
     617                 :             : 
     618                 :       11882 : static RPCHelpMan getmempooldescendants()
     619                 :             : {
     620                 :       11882 :     return RPCHelpMan{
     621                 :       11882 :         "getmempooldescendants",
     622         [ +  - ]:       23764 :         "If txid is in the mempool, returns all in-mempool descendants.\n",
     623                 :             :         {
     624   [ +  -  +  - ]:       23764 :             {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"},
     625   [ +  -  +  -  :       35646 :             {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "True for a json object, false for array of transaction ids"},
                   +  - ]
     626                 :             :         },
     627                 :             :         {
     628         [ +  - ]:       11882 :             RPCResult{"for verbose = false",
     629   [ +  -  +  - ]:       23764 :                 RPCResult::Type::ARR, "", "",
     630   [ +  -  +  -  :       47528 :                 {{RPCResult::Type::STR_HEX, "", "The transaction id of an in-mempool descendant transaction"}}},
          +  -  +  +  -  
                      - ]
     631         [ +  - ]:       23764 :             RPCResult{"for verbose = true",
     632   [ +  -  +  - ]:       23764 :                 RPCResult::Type::OBJ_DYN, "", "",
     633                 :             :                 {
     634   [ +  -  +  -  :       23764 :                     {RPCResult::Type::OBJ, "transactionid", "", MempoolEntryDescription()},
                   +  - ]
     635   [ +  -  +  +  :       35646 :                 }},
                   -  - ]
     636                 :             :         },
     637                 :       11882 :         RPCExamples{
     638   [ +  -  +  -  :       23764 :             HelpExampleCli("getmempooldescendants", "\"mytxid\"")
                   +  - ]
     639   [ +  -  +  -  :       47528 :             + HelpExampleRpc("getmempooldescendants", "\"mytxid\"")
                   +  - ]
     640         [ +  - ]:       11882 :         },
     641                 :       11882 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     642                 :             : {
     643                 :        9519 :     bool fVerbose = false;
     644         [ +  + ]:        9519 :     if (!request.params[1].isNull())
     645                 :          65 :         fVerbose = request.params[1].get_bool();
     646                 :             : 
     647                 :        9519 :     auto txid{Txid::FromUint256(ParseHashV(request.params[0], "txid"))};
     648                 :             : 
     649                 :        9519 :     const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
     650                 :        9519 :     LOCK(mempool.cs);
     651                 :             : 
     652         [ +  - ]:        9519 :     const auto it{mempool.GetIter(txid)};
     653         [ -  + ]:        9519 :     if (!it) {
     654   [ #  #  #  # ]:           0 :         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool");
     655                 :             :     }
     656                 :             : 
     657         [ +  - ]:        9519 :     CTxMemPool::setEntries setDescendants;
     658         [ +  - ]:        9519 :     mempool.CalculateDescendants(*it, setDescendants);
     659                 :             :     // CTxMemPool::CalculateDescendants will include the given tx
     660                 :        9519 :     setDescendants.erase(*it);
     661                 :             : 
     662         [ +  + ]:        9519 :     if (!fVerbose) {
     663                 :        9454 :         UniValue o(UniValue::VARR);
     664         [ +  + ]:      175782 :         for (CTxMemPool::txiter descendantIt : setDescendants) {
     665   [ +  -  +  -  :      166328 :             o.push_back(descendantIt->GetTx().GetHash().ToString());
                   +  - ]
     666                 :             :         }
     667                 :             : 
     668                 :             :         return o;
     669                 :           0 :     } else {
     670                 :          65 :         UniValue o(UniValue::VOBJ);
     671         [ +  + ]:        2144 :         for (CTxMemPool::txiter descendantIt : setDescendants) {
     672                 :        2079 :             const CTxMemPoolEntry &e = *descendantIt;
     673                 :        2079 :             UniValue info(UniValue::VOBJ);
     674         [ +  - ]:        2079 :             entryToJSON(mempool, info, e);
     675   [ +  -  +  - ]:        4158 :             o.pushKV(e.GetTx().GetHash().ToString(), std::move(info));
     676                 :        2079 :         }
     677                 :          65 :         return o;
     678                 :          65 :     }
     679         [ +  - ]:       19038 : },
     680   [ +  -  +  -  :      130702 :     };
          +  -  +  -  +  
          +  +  +  -  -  
                   -  - ]
     681   [ +  -  +  -  :       95056 : }
          +  -  +  -  +  
          -  +  -  -  -  
                   -  - ]
     682                 :             : 
     683                 :        3505 : static RPCHelpMan getmempoolcluster()
     684                 :             : {
     685                 :        3505 :     return RPCHelpMan{"getmempoolcluster",
     686         [ +  - ]:        7010 :         "Returns mempool data for given cluster\n",
     687                 :             :         {
     688   [ +  -  +  - ]:        7010 :             {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The txid of a transaction in the cluster"},
     689                 :             :         },
     690         [ +  - ]:        7010 :         RPCResult{
     691   [ +  -  +  -  :        7010 :             RPCResult::Type::OBJ, "", "", ClusterDescription()},
             +  -  +  - ]
     692                 :        3505 :         RPCExamples{
     693   [ +  -  +  -  :        7010 :             HelpExampleCli("getmempoolcluster", "txid")
                   +  - ]
     694   [ +  -  +  -  :       14020 :             + HelpExampleRpc("getmempoolcluster", "txid")
             +  -  +  - ]
     695         [ +  - ]:        3505 :         },
     696                 :        3505 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     697                 :             : {
     698                 :        1142 :     uint256 hash = ParseHashV(request.params[0], "txid");
     699                 :             : 
     700                 :        1142 :     const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
     701                 :        1142 :     LOCK(mempool.cs);
     702                 :             : 
     703         [ +  - ]:        1142 :     auto txid = Txid::FromUint256(hash);
     704         [ +  - ]:        1142 :     const auto entry{mempool.GetEntry(txid)};
     705         [ +  + ]:        1142 :     if (entry == nullptr) {
     706   [ +  -  +  - ]:           2 :         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool");
     707                 :             :     }
     708                 :             : 
     709         [ +  - ]:        1141 :     auto cluster = mempool.GetCluster(txid);
     710                 :             : 
     711                 :        1141 :     UniValue info(UniValue::VOBJ);
     712   [ +  -  +  - ]:        1141 :     clusterToJSON(mempool, info, cluster);
     713                 :        1141 :     return info;
     714         [ +  - ]:        2282 : },
     715   [ +  -  +  -  :       17525 :     };
             +  +  -  - ]
     716         [ +  - ]:        7010 : }
     717                 :             : 
     718                 :        3139 : static RPCHelpMan getmempoolentry()
     719                 :             : {
     720                 :        3139 :     return RPCHelpMan{
     721                 :        3139 :         "getmempoolentry",
     722         [ +  - ]:        6278 :         "Returns mempool data for given transaction\n",
     723                 :             :         {
     724   [ +  -  +  - ]:        6278 :             {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"},
     725                 :             :         },
     726         [ +  - ]:        6278 :         RPCResult{
     727   [ +  -  +  -  :        6278 :             RPCResult::Type::OBJ, "", "", MempoolEntryDescription()},
             +  -  +  - ]
     728                 :        3139 :         RPCExamples{
     729   [ +  -  +  -  :        6278 :             HelpExampleCli("getmempoolentry", "\"mytxid\"")
                   +  - ]
     730   [ +  -  +  -  :       12556 :             + HelpExampleRpc("getmempoolentry", "\"mytxid\"")
             +  -  +  - ]
     731         [ +  - ]:        3139 :         },
     732                 :        3139 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     733                 :             : {
     734                 :         776 :     auto txid{Txid::FromUint256(ParseHashV(request.params[0], "txid"))};
     735                 :             : 
     736                 :         776 :     const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
     737                 :         776 :     LOCK(mempool.cs);
     738                 :             : 
     739         [ +  - ]:         776 :     const auto entry{mempool.GetEntry(txid)};
     740         [ +  + ]:         776 :     if (entry == nullptr) {
     741   [ +  -  +  - ]:          12 :         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool");
     742                 :             :     }
     743                 :             : 
     744                 :         770 :     UniValue info(UniValue::VOBJ);
     745         [ +  - ]:         770 :     entryToJSON(mempool, info, *entry);
     746         [ +  - ]:         770 :     return info;
     747                 :         770 : },
     748   [ +  -  +  -  :       15695 :     };
             +  +  -  - ]
     749         [ +  - ]:        6278 : }
     750                 :             : 
     751                 :        2438 : static RPCHelpMan gettxspendingprevout()
     752                 :             : {
     753                 :        2438 :     return RPCHelpMan{"gettxspendingprevout",
     754         [ +  - ]:        4876 :         "Scans the mempool to find transactions spending any of the given outputs",
     755                 :             :         {
     756   [ +  -  +  - ]:        4876 :             {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The transaction outputs that we want to check, and within each, the txid (string) vout (numeric).",
     757                 :             :                 {
     758   [ +  -  +  - ]:        4876 :                     {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
     759                 :             :                         {
     760   [ +  -  +  - ]:        4876 :                             {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
     761   [ +  -  +  - ]:        4876 :                             {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
     762                 :             :                         },
     763                 :             :                     },
     764                 :             :                 },
     765                 :             :             },
     766                 :             :         },
     767         [ +  - ]:        4876 :         RPCResult{
     768   [ +  -  +  - ]:        4876 :             RPCResult::Type::ARR, "", "",
     769                 :             :             {
     770   [ +  -  +  - ]:        4876 :                 {RPCResult::Type::OBJ, "", "",
     771                 :             :                 {
     772   [ +  -  +  - ]:        4876 :                     {RPCResult::Type::STR_HEX, "txid", "the transaction id of the checked output"},
     773   [ +  -  +  - ]:        4876 :                     {RPCResult::Type::NUM, "vout", "the vout value of the checked output"},
     774   [ +  -  +  - ]:        4876 :                     {RPCResult::Type::STR_HEX, "spendingtxid", /*optional=*/true, "the transaction id of the mempool transaction spending this output (omitted if unspent)"},
     775                 :             :                 }},
     776                 :             :             }
     777   [ +  -  +  -  :       21942 :         },
          +  -  +  +  +  
             +  -  -  -  
                      - ]
     778                 :        2438 :         RPCExamples{
     779   [ +  -  +  -  :        4876 :             HelpExampleCli("gettxspendingprevout", "\"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":3}]\"")
                   +  - ]
     780   [ +  -  +  -  :        9752 :             + HelpExampleRpc("gettxspendingprevout", "\"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":3}]\"")
             +  -  +  - ]
     781         [ +  - ]:        2438 :         },
     782                 :        2438 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     783                 :             :         {
     784                 :          75 :             const UniValue& output_params = request.params[0].get_array();
     785   [ -  +  +  + ]:          75 :             if (output_params.empty()) {
     786   [ +  -  +  - ]:           2 :                 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, outputs are missing");
     787                 :             :             }
     788                 :             : 
     789                 :          74 :             std::vector<COutPoint> prevouts;
     790         [ +  - ]:          74 :             prevouts.reserve(output_params.size());
     791                 :             : 
     792   [ -  +  +  + ]:         146 :             for (unsigned int idx = 0; idx < output_params.size(); idx++) {
     793   [ +  -  +  - ]:          77 :                 const UniValue& o = output_params[idx].get_obj();
     794                 :             : 
     795   [ +  +  +  +  :         312 :                 RPCTypeCheckObj(o,
                   +  + ]
     796                 :             :                                 {
     797         [ +  - ]:          77 :                                     {"txid", UniValueType(UniValue::VSTR)},
     798         [ +  - ]:          77 :                                     {"vout", UniValueType(UniValue::VNUM)},
     799                 :             :                                 }, /*fAllowNull=*/false, /*fStrict=*/true);
     800                 :             : 
     801         [ +  - ]:          73 :                 const Txid txid = Txid::FromUint256(ParseHashO(o, "txid"));
     802   [ +  -  +  - ]:          73 :                 const int nOutput{o.find_value("vout").getInt<int>()};
     803         [ +  + ]:          73 :                 if (nOutput < 0) {
     804   [ +  -  +  - ]:           2 :                     throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout cannot be negative");
     805                 :             :                 }
     806                 :             : 
     807         [ +  - ]:          72 :                 prevouts.emplace_back(txid, nOutput);
     808                 :             :             }
     809                 :             : 
     810         [ +  - ]:          69 :             const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
     811         [ +  - ]:          69 :             LOCK(mempool.cs);
     812                 :             : 
     813                 :          69 :             UniValue result{UniValue::VARR};
     814                 :             : 
     815         [ +  + ]:         141 :             for (const COutPoint& prevout : prevouts) {
     816                 :          72 :                 UniValue o(UniValue::VOBJ);
     817   [ +  -  +  -  :         144 :                 o.pushKV("txid", prevout.hash.ToString());
             +  -  +  - ]
     818   [ +  -  +  -  :         144 :                 o.pushKV("vout", (uint64_t)prevout.n);
                   +  - ]
     819                 :             : 
     820         [ +  - ]:          72 :                 const CTransaction* spendingTx = mempool.GetConflictTx(prevout);
     821         [ +  + ]:          72 :                 if (spendingTx != nullptr) {
     822   [ +  -  +  -  :         138 :                     o.pushKV("spendingtxid", spendingTx->GetHash().ToString());
             +  -  +  - ]
     823                 :             :                 }
     824                 :             : 
     825         [ +  - ]:          72 :                 result.push_back(std::move(o));
     826                 :          72 :             }
     827                 :             : 
     828         [ +  - ]:          69 :             return result;
     829   [ +  -  +  -  :         150 :         },
             +  -  -  + ]
     830   [ +  -  +  -  :       29256 :     };
          +  -  +  -  +  
          +  +  +  +  +  
          -  -  -  -  -  
                      - ]
     831   [ +  -  +  -  :       29256 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  -  -  
                      - ]
     832                 :             : 
     833                 :        1266 : UniValue MempoolInfoToJSON(const CTxMemPool& pool)
     834                 :             : {
     835                 :             :     // Make sure this call is atomic in the pool.
     836                 :        1266 :     LOCK(pool.cs);
     837                 :        1266 :     UniValue ret(UniValue::VOBJ);
     838   [ +  -  +  -  :        2532 :     ret.pushKV("loaded", pool.GetLoadTried());
             +  -  +  - ]
     839   [ +  -  +  -  :        2532 :     ret.pushKV("size", (int64_t)pool.size());
             +  -  +  - ]
     840   [ +  -  +  -  :        2532 :     ret.pushKV("bytes", (int64_t)pool.GetTotalTxSize());
                   +  - ]
     841   [ +  -  +  -  :        2532 :     ret.pushKV("usage", (int64_t)pool.DynamicMemoryUsage());
             +  -  +  - ]
     842   [ +  -  +  -  :        2532 :     ret.pushKV("total_fee", ValueFromAmount(pool.GetTotalFee()));
                   +  - ]
     843   [ +  -  +  -  :        2532 :     ret.pushKV("maxmempool", pool.m_opts.max_size_bytes);
                   +  - ]
     844   [ +  -  +  -  :        2532 :     ret.pushKV("mempoolminfee", ValueFromAmount(std::max(pool.GetMinFee(), pool.m_opts.min_relay_feerate).GetFeePerK()));
             +  -  +  - ]
     845   [ +  -  +  -  :        2532 :     ret.pushKV("minrelaytxfee", ValueFromAmount(pool.m_opts.min_relay_feerate.GetFeePerK()));
                   +  - ]
     846   [ +  -  +  -  :        2532 :     ret.pushKV("incrementalrelayfee", ValueFromAmount(pool.m_opts.incremental_relay_feerate.GetFeePerK()));
                   +  - ]
     847   [ +  -  +  -  :        2532 :     ret.pushKV("unbroadcastcount", uint64_t{pool.GetUnbroadcastTxs().size()});
             +  -  +  - ]
     848   [ +  -  +  -  :        2532 :     ret.pushKV("fullrbf", true);
                   +  - ]
     849   [ +  -  +  -  :        2532 :     ret.pushKV("permitbaremultisig", pool.m_opts.permit_bare_multisig);
                   +  - ]
     850   [ +  +  +  -  :        3796 :     ret.pushKV("maxdatacarriersize", pool.m_opts.max_datacarrier_bytes.value_or(0));
             +  -  +  - ]
     851   [ +  -  +  -  :        2532 :     ret.pushKV("limitclustercount", pool.m_opts.limits.cluster_count);
                   +  - ]
     852   [ +  -  +  -  :        2532 :     ret.pushKV("limitclustersize", pool.m_opts.limits.cluster_size_vbytes);
                   +  - ]
     853         [ +  - ]:        1266 :     return ret;
     854                 :        1266 : }
     855                 :             : 
     856                 :        3628 : static RPCHelpMan getmempoolinfo()
     857                 :             : {
     858                 :        3628 :     return RPCHelpMan{"getmempoolinfo",
     859         [ +  - ]:        7256 :         "Returns details on the active state of the TX memory pool.",
     860                 :             :         {},
     861         [ +  - ]:        7256 :         RPCResult{
     862         [ +  - ]:        7256 :             RPCResult::Type::OBJ, "", "",
     863                 :             :             {
     864   [ +  -  +  - ]:        7256 :                 {RPCResult::Type::BOOL, "loaded", "True if the initial load attempt of the persisted mempool finished"},
     865   [ +  -  +  - ]:        7256 :                 {RPCResult::Type::NUM, "size", "Current tx count"},
     866   [ +  -  +  - ]:        7256 :                 {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"},
     867   [ +  -  +  - ]:        7256 :                 {RPCResult::Type::NUM, "usage", "Total memory usage for the mempool"},
     868   [ +  -  +  - ]:        7256 :                 {RPCResult::Type::STR_AMOUNT, "total_fee", "Total fees for the mempool in " + CURRENCY_UNIT + ", ignoring modified fees through prioritisetransaction"},
     869   [ +  -  +  - ]:        7256 :                 {RPCResult::Type::NUM, "maxmempool", "Maximum memory usage for the mempool"},
     870   [ +  -  +  - ]:        7256 :                 {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"},
     871   [ +  -  +  - ]:        7256 :                 {RPCResult::Type::STR_AMOUNT, "minrelaytxfee", "Current minimum relay fee for transactions"},
     872   [ +  -  +  - ]:        7256 :                 {RPCResult::Type::NUM, "incrementalrelayfee", "minimum fee rate increment for mempool limiting or replacement in " + CURRENCY_UNIT + "/kvB"},
     873   [ +  -  +  - ]:        7256 :                 {RPCResult::Type::NUM, "unbroadcastcount", "Current number of transactions that haven't passed initial broadcast yet"},
     874   [ +  -  +  - ]:        7256 :                 {RPCResult::Type::BOOL, "fullrbf", "True if the mempool accepts RBF without replaceability signaling inspection (DEPRECATED)"},
     875   [ +  -  +  - ]:        7256 :                 {RPCResult::Type::BOOL, "permitbaremultisig", "True if the mempool accepts transactions with bare multisig outputs"},
     876   [ +  -  +  - ]:        7256 :                 {RPCResult::Type::NUM, "maxdatacarriersize", "Maximum number of bytes that can be used by OP_RETURN outputs in the mempool"},
     877   [ +  -  +  - ]:        7256 :                 {RPCResult::Type::NUM, "limitclustercount", "Maximum number of transactions that can be in a cluster (configured by -limitclustercount)"},
     878   [ +  -  +  - ]:        7256 :                 {RPCResult::Type::NUM, "limitclustersize", "Maximum size of a cluster in virtual bytes (configured by -limitclustersize)"},
     879   [ +  -  +  -  :      112468 :             }},
             +  +  -  - ]
     880                 :        3628 :         RPCExamples{
     881   [ +  -  +  -  :        7256 :             HelpExampleCli("getmempoolinfo", "")
                   +  - ]
     882   [ +  -  +  -  :       14512 :             + HelpExampleRpc("getmempoolinfo", "")
             +  -  +  - ]
     883         [ +  - ]:        3628 :         },
     884                 :        3628 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     885                 :             : {
     886                 :        1265 :     return MempoolInfoToJSON(EnsureAnyMemPool(request.context));
     887                 :             : },
     888   [ +  -  +  - ]:       14512 :     };
     889   [ +  -  +  -  :       54420 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  -  - ]
     890                 :             : 
     891                 :        2366 : static RPCHelpMan importmempool()
     892                 :             : {
     893                 :        2366 :     return RPCHelpMan{
     894                 :        2366 :         "importmempool",
     895         [ +  - ]:        7098 :         "Import a mempool.dat file and attempt to add its contents to the mempool.\n"
     896                 :             :         "Warning: Importing untrusted files is dangerous, especially if metadata from the file is taken over.",
     897                 :             :         {
     898   [ +  -  +  - ]:        4732 :             {"filepath", RPCArg::Type::STR, RPCArg::Optional::NO, "The mempool file"},
     899         [ +  - ]:        4732 :             {"options",
     900                 :             :              RPCArg::Type::OBJ_NAMED_PARAMS,
     901                 :        2366 :              RPCArg::Optional::OMITTED,
     902         [ +  - ]:        4732 :              "",
     903                 :             :              {
     904   [ +  -  +  - ]:        4732 :                  {"use_current_time", RPCArg::Type::BOOL, RPCArg::Default{true},
     905         [ +  - ]:        4732 :                   "Whether to use the current system time or use the entry time metadata from the mempool file.\n"
     906                 :             :                   "Warning: Importing untrusted metadata may lead to unexpected issues and undesirable behavior."},
     907   [ +  -  +  - ]:        4732 :                  {"apply_fee_delta_priority", RPCArg::Type::BOOL, RPCArg::Default{false},
     908         [ +  - ]:        4732 :                   "Whether to apply the fee delta metadata from the mempool file.\n"
     909                 :             :                   "It will be added to any existing fee deltas.\n"
     910                 :             :                   "The fee delta can be set by the prioritisetransaction RPC.\n"
     911                 :             :                   "Warning: Importing untrusted metadata may lead to unexpected issues and undesirable behavior.\n"
     912                 :             :                   "Only set this bool if you understand what it does."},
     913   [ +  -  +  - ]:        4732 :                  {"apply_unbroadcast_set", RPCArg::Type::BOOL, RPCArg::Default{false},
     914         [ +  - ]:        4732 :                   "Whether to apply the unbroadcast set metadata from the mempool file.\n"
     915                 :             :                   "Warning: Importing untrusted metadata may lead to unexpected issues and undesirable behavior."},
     916                 :             :              },
     917         [ +  - ]:        2366 :              RPCArgOptions{.oneline_description = "options"}},
     918                 :             :         },
     919   [ +  -  +  -  :        4732 :         RPCResult{RPCResult::Type::OBJ, "", "", std::vector<RPCResult>{}},
             +  -  +  - ]
     920   [ +  -  +  -  :        7098 :         RPCExamples{HelpExampleCli("importmempool", "/path/to/mempool.dat") + HelpExampleRpc("importmempool", "/path/to/mempool.dat")},
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     921                 :        2366 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
     922                 :           3 :             const NodeContext& node{EnsureAnyNodeContext(request.context)};
     923                 :             : 
     924                 :           3 :             CTxMemPool& mempool{EnsureMemPool(node)};
     925                 :           3 :             ChainstateManager& chainman = EnsureChainman(node);
     926                 :           3 :             Chainstate& chainstate = chainman.ActiveChainstate();
     927                 :             : 
     928         [ -  + ]:           3 :             if (chainman.IsInitialBlockDownload()) {
     929   [ #  #  #  # ]:           0 :                 throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Can only import the mempool after the block download and sync is done.");
     930                 :             :             }
     931                 :             : 
     932                 :           3 :             const fs::path load_path{fs::u8path(self.Arg<std::string_view>("filepath"))};
     933   [ +  -  +  -  :           3 :             const UniValue& use_current_time{request.params[1]["use_current_time"]};
                   +  - ]
     934   [ +  -  +  -  :           3 :             const UniValue& apply_fee_delta{request.params[1]["apply_fee_delta_priority"]};
                   +  - ]
     935   [ +  -  +  -  :           3 :             const UniValue& apply_unbroadcast{request.params[1]["apply_unbroadcast_set"]};
                   +  - ]
     936         [ -  + ]:           3 :             node::ImportMempoolOptions opts{
     937   [ -  +  -  - ]:           3 :                 .use_current_time = use_current_time.isNull() ? true : use_current_time.get_bool(),
     938   [ +  +  +  - ]:           3 :                 .apply_fee_delta_priority = apply_fee_delta.isNull() ? false : apply_fee_delta.get_bool(),
     939   [ +  +  +  - ]:           3 :                 .apply_unbroadcast_set = apply_unbroadcast.isNull() ? false : apply_unbroadcast.get_bool(),
     940   [ -  +  +  +  :           5 :             };
                   +  + ]
     941                 :             : 
     942   [ +  -  -  + ]:           3 :             if (!node::LoadMempool(mempool, load_path, chainstate, std::move(opts))) {
     943   [ #  #  #  # ]:           0 :                 throw JSONRPCError(RPC_MISC_ERROR, "Unable to import mempool file, see debug.log for details.");
     944                 :             :             }
     945                 :             : 
     946                 :           3 :             UniValue ret{UniValue::VOBJ};
     947                 :           3 :             return ret;
     948                 :           6 :         },
     949   [ +  -  +  -  :       26026 :     };
          +  -  +  +  +  
             +  -  -  -  
                      - ]
     950   [ +  -  +  -  :       21294 : }
          +  -  +  -  +  
             -  -  -  -  
                      - ]
     951                 :             : 
     952                 :        2367 : static RPCHelpMan savemempool()
     953                 :             : {
     954                 :        2367 :     return RPCHelpMan{
     955                 :        2367 :         "savemempool",
     956         [ +  - ]:        4734 :         "Dumps the mempool to disk. It will fail until the previous dump is fully loaded.\n",
     957                 :             :         {},
     958         [ +  - ]:        4734 :         RPCResult{
     959         [ +  - ]:        4734 :             RPCResult::Type::OBJ, "", "",
     960                 :             :             {
     961   [ +  -  +  - ]:        4734 :                 {RPCResult::Type::STR, "filename", "the directory and file where the mempool was saved"},
     962   [ +  -  +  -  :        7101 :             }},
             +  +  -  - ]
     963                 :        2367 :         RPCExamples{
     964   [ +  -  +  -  :        4734 :             HelpExampleCli("savemempool", "")
                   +  - ]
     965   [ +  -  +  -  :        9468 :             + HelpExampleRpc("savemempool", "")
             +  -  +  - ]
     966         [ +  - ]:        2367 :         },
     967                 :        2367 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     968                 :             : {
     969                 :           4 :     const ArgsManager& args{EnsureAnyArgsman(request.context)};
     970                 :           4 :     const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
     971                 :             : 
     972         [ -  + ]:           4 :     if (!mempool.GetLoadTried()) {
     973   [ #  #  #  # ]:           0 :         throw JSONRPCError(RPC_MISC_ERROR, "The mempool was not loaded yet");
     974                 :             :     }
     975                 :             : 
     976                 :           4 :     const fs::path& dump_path = MempoolPath(args);
     977                 :             : 
     978   [ +  -  +  + ]:           4 :     if (!DumpMempool(mempool, dump_path)) {
     979   [ +  -  +  - ]:           2 :         throw JSONRPCError(RPC_MISC_ERROR, "Unable to dump mempool to disk");
     980                 :             :     }
     981                 :             : 
     982                 :           3 :     UniValue ret(UniValue::VOBJ);
     983   [ +  -  +  -  :           6 :     ret.pushKV("filename", dump_path.utf8string());
             +  -  +  - ]
     984                 :             : 
     985                 :           6 :     return ret;
     986                 :           0 : },
     987   [ +  -  +  - ]:        9468 :     };
     988         [ +  - ]:        2367 : }
     989                 :             : 
     990                 :        5146 : static std::vector<RPCResult> OrphanDescription()
     991                 :             : {
     992                 :        5146 :     return {
     993   [ +  -  +  - ]:       10292 :         RPCResult{RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
     994   [ +  -  +  - ]:       10292 :         RPCResult{RPCResult::Type::STR_HEX, "wtxid", "The transaction witness hash in hex"},
     995   [ +  -  +  - ]:       10292 :         RPCResult{RPCResult::Type::NUM, "bytes", "The serialized transaction size in bytes"},
     996   [ +  -  +  - ]:       10292 :         RPCResult{RPCResult::Type::NUM, "vsize", "The virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted."},
     997   [ +  -  +  - ]:       10292 :         RPCResult{RPCResult::Type::NUM, "weight", "The transaction weight as defined in BIP 141."},
     998   [ +  -  +  - ]:       10292 :         RPCResult{RPCResult::Type::ARR, "from", "",
     999                 :             :         {
    1000   [ +  -  +  - ]:       10292 :             RPCResult{RPCResult::Type::NUM, "peer_id", "Peer ID"},
    1001   [ +  -  +  +  :       15438 :         }},
                   -  - ]
    1002   [ +  -  +  +  :       46314 :     };
                   -  - ]
    1003   [ +  -  +  -  :       36022 : }
          +  -  +  -  +  
          -  +  -  +  -  
                   -  - ]
    1004                 :             : 
    1005                 :          43 : static UniValue OrphanToJSON(const node::TxOrphanage::OrphanInfo& orphan)
    1006                 :             : {
    1007                 :          43 :     UniValue o(UniValue::VOBJ);
    1008   [ +  -  +  -  :          86 :     o.pushKV("txid", orphan.tx->GetHash().ToString());
             +  -  +  - ]
    1009   [ +  -  +  -  :          86 :     o.pushKV("wtxid", orphan.tx->GetWitnessHash().ToString());
             +  -  +  - ]
    1010   [ +  -  +  -  :          86 :     o.pushKV("bytes", orphan.tx->GetTotalSize());
             +  -  +  - ]
    1011   [ +  -  +  -  :          86 :     o.pushKV("vsize", GetVirtualTransactionSize(*orphan.tx));
             +  -  +  - ]
    1012   [ +  -  +  -  :          86 :     o.pushKV("weight", GetTransactionWeight(*orphan.tx));
                   +  - ]
    1013                 :          43 :     UniValue from(UniValue::VARR);
    1014         [ +  + ]:          93 :     for (const auto fromPeer: orphan.announcers) {
    1015   [ +  -  +  - ]:          50 :         from.push_back(fromPeer);
    1016                 :             :     }
    1017   [ +  -  +  -  :          86 :     o.pushKV("from", from);
                   +  - ]
    1018                 :          43 :     return o;
    1019                 :          43 : }
    1020                 :             : 
    1021                 :        2573 : static RPCHelpMan getorphantxs()
    1022                 :             : {
    1023                 :        2573 :     return RPCHelpMan{
    1024                 :        2573 :         "getorphantxs",
    1025         [ +  - ]:        5146 :         "Shows transactions in the tx orphanage.\n"
    1026                 :             :         "\nEXPERIMENTAL warning: this call may be changed in future releases.\n",
    1027                 :             :         {
    1028   [ +  -  +  -  :        7719 :             {"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",
                   +  - ]
    1029         [ +  - ]:        5146 :              RPCArgOptions{.skip_type_check = true}},
    1030                 :             :         },
    1031                 :             :         {
    1032         [ +  - ]:        2573 :             RPCResult{"for verbose = 0",
    1033   [ +  -  +  - ]:        5146 :                 RPCResult::Type::ARR, "", "",
    1034                 :             :                 {
    1035   [ +  -  +  - ]:        5146 :                     {RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
    1036   [ +  -  +  +  :        7719 :                 }},
                   -  - ]
    1037         [ +  - ]:        5146 :             RPCResult{"for verbose = 1",
    1038   [ +  -  +  - ]:        5146 :                 RPCResult::Type::ARR, "", "",
    1039                 :             :                 {
    1040   [ +  -  +  -  :        5146 :                     {RPCResult::Type::OBJ, "", "", OrphanDescription()},
                   +  - ]
    1041   [ +  -  +  +  :        7719 :                 }},
                   -  - ]
    1042         [ +  - ]:        5146 :             RPCResult{"for verbose = 2",
    1043   [ +  -  +  - ]:        5146 :                 RPCResult::Type::ARR, "", "",
    1044                 :             :                 {
    1045   [ +  -  +  - ]:        5146 :                     {RPCResult::Type::OBJ, "", "",
    1046   [ +  -  +  -  :       12865 :                         Cat<std::vector<RPCResult>>(
             +  +  -  - ]
    1047         [ +  - ]:        5146 :                             OrphanDescription(),
    1048   [ +  -  +  - ]:        5146 :                             {{RPCResult::Type::STR_HEX, "hex", "The serialized, hex-encoded transaction data"}}
    1049                 :             :                         )
    1050                 :             :                     },
    1051   [ +  -  +  +  :        7719 :                 }},
                   -  - ]
    1052                 :             :         },
    1053                 :        2573 :         RPCExamples{
    1054   [ +  -  +  -  :        5146 :             HelpExampleCli("getorphantxs", "2")
                   +  - ]
    1055   [ +  -  +  -  :       10292 :             + HelpExampleRpc("getorphantxs", "2")
                   +  - ]
    1056         [ +  - ]:        2573 :         },
    1057                 :        2573 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
    1058                 :             :         {
    1059                 :         218 :             const NodeContext& node = EnsureAnyNodeContext(request.context);
    1060                 :         218 :             PeerManager& peerman = EnsurePeerman(node);
    1061                 :         218 :             std::vector<node::TxOrphanage::OrphanInfo> orphanage = peerman.GetOrphanTransactions();
    1062                 :             : 
    1063   [ +  -  +  + ]:         218 :             int verbosity{ParseVerbosity(request.params[0], /*default_verbosity=*/0, /*allow_bool*/false)};
    1064                 :             : 
    1065                 :         216 :             UniValue ret(UniValue::VARR);
    1066                 :             : 
    1067         [ +  + ]:         216 :             if (verbosity == 0) {
    1068         [ +  + ]:       18479 :                 for (auto const& orphan : orphanage) {
    1069   [ +  -  +  -  :       18298 :                     ret.push_back(orphan.tx->GetHash().ToString());
                   +  - ]
    1070                 :             :                 }
    1071         [ +  + ]:          35 :             } else if (verbosity == 1) {
    1072         [ +  + ]:          55 :                 for (auto const& orphan : orphanage) {
    1073   [ +  -  +  - ]:          32 :                     ret.push_back(OrphanToJSON(orphan));
    1074                 :             :                 }
    1075         [ +  + ]:          12 :             } else if (verbosity == 2) {
    1076         [ +  + ]:          21 :                 for (auto const& orphan : orphanage) {
    1077         [ +  - ]:          11 :                     UniValue o{OrphanToJSON(orphan)};
    1078   [ +  -  +  -  :          22 :                     o.pushKV("hex", EncodeHexTx(*orphan.tx));
             +  -  +  - ]
    1079   [ +  -  +  - ]:          11 :                     ret.push_back(o);
    1080                 :          11 :                 }
    1081                 :             :             } else {
    1082   [ +  -  +  -  :           4 :                 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid verbosity value " + ToString(verbosity));
                   +  - ]
    1083                 :             :             }
    1084                 :             : 
    1085                 :         214 :             return ret;
    1086                 :         220 :         },
    1087   [ +  -  +  -  :       28303 :     };
          +  -  +  -  +  
          +  +  +  -  -  
                   -  - ]
    1088   [ +  -  +  -  :       20584 : }
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  -  - ]
    1089                 :             : 
    1090                 :        2481 : static RPCHelpMan submitpackage()
    1091                 :             : {
    1092                 :        2481 :     return RPCHelpMan{"submitpackage",
    1093         [ +  - ]:        4962 :         "Submit a package of raw transactions (serialized, hex-encoded) to local node.\n"
    1094                 :             :         "The package will be validated according to consensus and mempool policy rules. If any transaction passes, it will be accepted to mempool.\n"
    1095                 :             :         "This RPC is experimental and the interface may be unstable. Refer to doc/policy/packages.md for documentation on package policies.\n"
    1096                 :             :         "Warning: successful submission does not mean the transactions will propagate throughout the network.\n"
    1097                 :             :         ,
    1098                 :             :         {
    1099   [ +  -  +  - ]:        4962 :             {"package", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of raw transactions.\n"
    1100                 :             :                 "The package must consist of a transaction with (some, all, or none of) its unconfirmed parents. A single transaction is permitted.\n"
    1101                 :             :                 "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"
    1102                 :             :                 "The package must be topologically sorted, with the child being the last element in the array if there are multiple elements.",
    1103                 :             :                 {
    1104   [ +  -  +  - ]:        4962 :                     {"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
    1105                 :             :                 },
    1106                 :             :             },
    1107   [ +  -  +  -  :        4962 :             {"maxfeerate", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK())},
                   +  - ]
    1108         [ +  - ]:        4962 :              "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT +
    1109                 :        2481 :                  "/kvB.\nFee rates larger than 1BTC/kvB are rejected.\nSet to 0 to accept any fee rate."},
    1110   [ +  -  +  -  :        4962 :             {"maxburnamount", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_BURN_AMOUNT)},
                   +  - ]
    1111         [ +  - ]:        4962 :              "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"
    1112                 :             :              "If burning funds through unspendable outputs is desired, increase this value.\n"
    1113                 :        2481 :              "This check is based on heuristics and does not guarantee spendability of outputs.\n"
    1114                 :             :             },
    1115                 :             :         },
    1116         [ +  - ]:        4962 :         RPCResult{
    1117   [ +  -  +  - ]:        4962 :             RPCResult::Type::OBJ, "", "",
    1118                 :             :             {
    1119   [ +  -  +  - ]:        4962 :                 {RPCResult::Type::STR, "package_msg", "The transaction package result message. \"success\" indicates all transactions were accepted into or are already in the mempool."},
    1120   [ +  -  +  - ]:        4962 :                 {RPCResult::Type::OBJ_DYN, "tx-results", "The transaction results keyed by wtxid. An entry is returned for every submitted wtxid.",
    1121                 :             :                 {
    1122   [ +  -  +  - ]:        4962 :                     {RPCResult::Type::OBJ, "wtxid", "transaction wtxid", {
    1123   [ +  -  +  - ]:        4962 :                         {RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
    1124   [ +  -  +  - ]:        4962 :                         {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."},
    1125   [ +  -  +  - ]:        4962 :                         {RPCResult::Type::NUM, "vsize", /*optional=*/true, "Sigops-adjusted virtual transaction size."},
    1126   [ +  -  +  - ]:        4962 :                         {RPCResult::Type::OBJ, "fees", /*optional=*/true, "Transaction fees", {
    1127   [ +  -  +  - ]:        4962 :                             {RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT},
    1128   [ +  -  +  - ]:        4962 :                             {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."},
    1129   [ +  -  +  - ]:        4962 :                             {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.",
    1130   [ +  -  +  - ]:        4962 :                                 {{RPCResult::Type::STR_HEX, "", "transaction wtxid in hex"},
    1131                 :             :                             }},
    1132                 :             :                         }},
    1133   [ +  -  +  - ]:        4962 :                         {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."},
    1134                 :             :                     }}
    1135                 :             :                 }},
    1136   [ +  -  +  - ]:        4962 :                 {RPCResult::Type::ARR, "replaced-transactions", /*optional=*/true, "List of txids of replaced transactions",
    1137                 :             :                 {
    1138   [ +  -  +  - ]:        4962 :                     {RPCResult::Type::STR_HEX, "", "The transaction id"},
    1139                 :             :                 }},
    1140                 :             :             },
    1141   [ +  -  +  -  :       71949 :         },
          +  -  +  -  +  
          -  +  -  +  -  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  -  -  -  
          -  -  -  -  -  
             -  -  -  - ]
    1142                 :        2481 :         RPCExamples{
    1143   [ +  -  +  -  :        4962 :             HelpExampleRpc("submitpackage", R"(["raw-parent-tx-1", "raw-parent-tx-2", "raw-child-tx"])") +
                   +  - ]
    1144   [ +  -  +  -  :        7443 :             HelpExampleCli("submitpackage", R"('["raw-tx-without-unconfirmed-parents"]')")
             +  -  +  - ]
    1145         [ +  - ]:        2481 :         },
    1146                 :        2481 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
    1147                 :             :         {
    1148                 :         118 :             const UniValue raw_transactions = request.params[0].get_array();
    1149   [ -  +  +  +  :         118 :             if (raw_transactions.empty() || raw_transactions.size() > MAX_PACKAGE_COUNT) {
                   +  + ]
    1150                 :           2 :                 throw JSONRPCError(RPC_INVALID_PARAMETER,
    1151   [ +  -  +  -  :           6 :                                    "Array must contain between 1 and " + ToString(MAX_PACKAGE_COUNT) + " transactions.");
                   +  - ]
    1152                 :             :             }
    1153                 :             : 
    1154                 :             :             // Fee check needs to be run with chainstate and package context
    1155   [ +  -  +  - ]:         116 :             const CFeeRate max_raw_tx_fee_rate{ParseFeeRate(self.Arg<UniValue>("maxfeerate"))};
    1156         [ +  + ]:         116 :             std::optional<CFeeRate> client_maxfeerate{max_raw_tx_fee_rate};
    1157                 :             :             // 0-value is special; it's mapped to no sanity check
    1158         [ +  + ]:         116 :             if (max_raw_tx_fee_rate == CFeeRate(0)) {
    1159                 :          29 :                 client_maxfeerate = std::nullopt;
    1160                 :             :             }
    1161                 :             : 
    1162                 :             :             // Burn sanity check is run with no context
    1163   [ +  -  +  +  :         116 :             const CAmount max_burn_amount = request.params[2].isNull() ? 0 : AmountFromValue(request.params[2]);
             +  -  +  - ]
    1164                 :             : 
    1165                 :         116 :             std::vector<CTransactionRef> txns;
    1166   [ -  +  +  - ]:         116 :             txns.reserve(raw_transactions.size());
    1167   [ +  -  +  + ]:         495 :             for (const auto& rawtx : raw_transactions.getValues()) {
    1168         [ +  - ]:         381 :                 CMutableTransaction mtx;
    1169   [ +  -  +  -  :         381 :                 if (!DecodeHexTx(mtx, rawtx.get_str())) {
                   +  + ]
    1170                 :           1 :                     throw JSONRPCError(RPC_DESERIALIZATION_ERROR,
    1171   [ +  -  +  -  :           3 :                                        "TX decode failed: " + rawtx.get_str() + " Make sure the tx has at least one input.");
                   +  - ]
    1172                 :             :                 }
    1173                 :             : 
    1174         [ +  + ]:         893 :                 for (const auto& out : mtx.vout) {
    1175   [ +  +  +  -  :         514 :                     if((out.scriptPubKey.IsUnspendable() || !out.scriptPubKey.HasValidOps()) && out.nValue > max_burn_amount) {
             -  +  +  + ]
    1176   [ +  -  +  - ]:           2 :                         throw JSONRPCTransactionError(TransactionError::MAX_BURN_EXCEEDED);
    1177                 :             :                     }
    1178                 :             :                 }
    1179                 :             : 
    1180   [ +  -  +  - ]:        1137 :                 txns.emplace_back(MakeTransactionRef(std::move(mtx)));
    1181                 :         381 :             }
    1182         [ +  - ]:         114 :             CHECK_NONFATAL(!txns.empty());
    1183   [ -  +  +  +  :         114 :             if (txns.size() > 1 && !IsChildWithParentsTree(txns)) {
             +  -  +  + ]
    1184   [ +  -  +  - ]:           4 :                 throw JSONRPCTransactionError(TransactionError::INVALID_PACKAGE, "package topology disallowed. not child-with-parents or parents depend on each other.");
    1185                 :             :             }
    1186                 :             : 
    1187         [ +  - ]:         112 :             NodeContext& node = EnsureAnyNodeContext(request.context);
    1188         [ +  - ]:         112 :             CTxMemPool& mempool = EnsureMemPool(node);
    1189   [ +  -  +  - ]:         112 :             Chainstate& chainstate = EnsureChainman(node).ActiveChainstate();
    1190   [ +  -  +  - ]:         336 :             const auto package_result = WITH_LOCK(::cs_main, return ProcessNewPackage(chainstate, mempool, txns, /*test_accept=*/ false, client_maxfeerate));
    1191                 :             : 
    1192         [ +  - ]:         112 :             std::string package_msg = "success";
    1193                 :             : 
    1194                 :             :             // First catch package-wide errors, continue if we can
    1195   [ +  -  +  - ]:         112 :             switch(package_result.m_state.GetResult()) {
    1196                 :          57 :                 case PackageValidationResult::PCKG_RESULT_UNSET:
    1197                 :          57 :                 {
    1198                 :             :                     // Belt-and-suspenders check; everything should be successful here
    1199   [ -  +  +  - ]:          57 :                     CHECK_NONFATAL(package_result.m_tx_results.size() == txns.size());
    1200         [ +  + ]:         266 :                     for (const auto& tx : txns) {
    1201   [ +  -  +  - ]:         209 :                         CHECK_NONFATAL(mempool.exists(tx->GetHash()));
    1202                 :             :                     }
    1203                 :             :                     break;
    1204                 :             :                 }
    1205                 :           0 :                 case PackageValidationResult::PCKG_MEMPOOL_ERROR:
    1206                 :           0 :                 {
    1207                 :             :                     // This only happens with internal bug; user should stop and report
    1208                 :           0 :                     throw JSONRPCTransactionError(TransactionError::MEMPOOL_ERROR,
    1209   [ #  #  #  # ]:           0 :                         package_result.m_state.GetRejectReason());
    1210                 :             :                 }
    1211                 :          55 :                 case PackageValidationResult::PCKG_POLICY:
    1212                 :          55 :                 case PackageValidationResult::PCKG_TX:
    1213                 :          55 :                 {
    1214                 :             :                     // Package-wide error we want to return, but we also want to return individual responses
    1215         [ +  - ]:          55 :                     package_msg = package_result.m_state.ToString();
    1216   [ -  +  +  +  :          57 :                     CHECK_NONFATAL(package_result.m_tx_results.size() == txns.size() ||
             +  -  +  - ]
    1217                 :             :                             package_result.m_tx_results.empty());
    1218                 :             :                     break;
    1219                 :             :                 }
    1220                 :             :             }
    1221                 :             : 
    1222                 :         112 :             size_t num_broadcast{0};
    1223         [ +  + ]:         483 :             for (const auto& tx : txns) {
    1224                 :             :                 // We don't want to re-submit the txn for validation in BroadcastTransaction
    1225   [ +  -  +  + ]:         371 :                 if (!mempool.exists(tx->GetHash())) {
    1226                 :         100 :                     continue;
    1227                 :             :                 }
    1228                 :             : 
    1229                 :             :                 // We do not expect an error here; we are only broadcasting things already/still in mempool
    1230         [ +  - ]:         271 :                 std::string err_string;
    1231   [ +  -  +  - ]:         271 :                 const auto err = BroadcastTransaction(node,
    1232                 :             :                                                       tx,
    1233                 :             :                                                       err_string,
    1234         [ +  - ]:         271 :                                                       /*max_tx_fee=*/0,
    1235                 :             :                                                       node::TxBroadcast::MEMPOOL_AND_BROADCAST_TO_ALL,
    1236                 :             :                                                       /*wait_callback=*/true);
    1237         [ -  + ]:         271 :                 if (err != TransactionError::OK) {
    1238                 :           0 :                     throw JSONRPCTransactionError(err,
    1239         [ #  # ]:           0 :                         strprintf("transaction broadcast failed: %s (%d transactions were broadcast successfully)",
    1240         [ #  # ]:           0 :                             err_string, num_broadcast));
    1241                 :             :                 }
    1242                 :         271 :                 num_broadcast++;
    1243                 :         271 :             }
    1244                 :             : 
    1245                 :         112 :             UniValue rpc_result{UniValue::VOBJ};
    1246   [ +  -  +  -  :         224 :             rpc_result.pushKV("package_msg", package_msg);
                   +  - ]
    1247                 :         224 :             UniValue tx_result_map{UniValue::VOBJ};
    1248                 :         224 :             std::set<Txid> replaced_txids;
    1249         [ +  + ]:         483 :             for (const auto& tx : txns) {
    1250                 :         371 :                 UniValue result_inner{UniValue::VOBJ};
    1251   [ +  -  +  -  :         742 :                 result_inner.pushKV("txid", tx->GetHash().GetHex());
             +  -  +  - ]
    1252         [ +  - ]:         371 :                 const auto wtxid_hex = tx->GetWitnessHash().GetHex();
    1253                 :         371 :                 auto it = package_result.m_tx_results.find(tx->GetWitnessHash());
    1254         [ +  + ]:         371 :                 if (it == package_result.m_tx_results.end()) {
    1255                 :             :                     // No per-tx result for this wtxid
    1256                 :             :                     // Current invariant: per-tx results are all-or-none (every member or empty on package abort).
    1257                 :             :                     // If any exist yet this one is missing, it's an unexpected partial map.
    1258         [ +  - ]:           6 :                     CHECK_NONFATAL(package_result.m_tx_results.empty());
    1259   [ +  -  +  -  :          12 :                     result_inner.pushKV("error", "package-not-validated");
                   +  - ]
    1260   [ -  +  +  - ]:          18 :                     tx_result_map.pushKV(wtxid_hex, std::move(result_inner));
    1261                 :           6 :                     continue;
    1262                 :             :                 }
    1263   [ -  +  +  - ]:         365 :                 const auto& tx_result = it->second;
    1264   [ -  +  +  - ]:         365 :                 switch(it->second.m_result_type) {
    1265                 :           0 :                 case MempoolAcceptResult::ResultType::DIFFERENT_WITNESS:
    1266   [ #  #  #  #  :           0 :                     result_inner.pushKV("other-wtxid", it->second.m_other_wtxid.value().GetHex());
          #  #  #  #  #  
                      # ]
    1267                 :           0 :                     break;
    1268                 :          95 :                 case MempoolAcceptResult::ResultType::INVALID:
    1269   [ +  -  +  -  :         190 :                     result_inner.pushKV("error", it->second.m_state.ToString());
             +  -  +  - ]
    1270                 :          95 :                     break;
    1271                 :         270 :                 case MempoolAcceptResult::ResultType::VALID:
    1272                 :         270 :                 case MempoolAcceptResult::ResultType::MEMPOOL_ENTRY:
    1273   [ +  -  +  -  :         540 :                     result_inner.pushKV("vsize", int64_t{it->second.m_vsize.value()});
             +  -  +  - ]
    1274                 :         270 :                     UniValue fees(UniValue::VOBJ);
    1275   [ +  -  +  -  :         540 :                     fees.pushKV("base", ValueFromAmount(it->second.m_base_fees.value()));
             +  -  +  - ]
    1276         [ +  + ]:         270 :                     if (tx_result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
    1277                 :             :                         // Effective feerate is not provided for MEMPOOL_ENTRY transactions even
    1278                 :             :                         // though modified fees is known, because it is unknown whether package
    1279                 :             :                         // feerate was used when it was originally submitted.
    1280   [ +  -  +  -  :         348 :                         fees.pushKV("effective-feerate", ValueFromAmount(tx_result.m_effective_feerate.value().GetFeePerK()));
             +  -  +  - ]
    1281                 :         174 :                         UniValue effective_includes_res(UniValue::VARR);
    1282   [ +  -  +  + ]:         396 :                         for (const auto& wtxid : tx_result.m_wtxids_fee_calculations.value()) {
    1283   [ +  -  +  -  :         222 :                             effective_includes_res.push_back(wtxid.ToString());
                   +  - ]
    1284                 :             :                         }
    1285   [ +  -  +  - ]:         348 :                         fees.pushKV("effective-includes", std::move(effective_includes_res));
    1286                 :         174 :                     }
    1287   [ +  -  +  - ]:         540 :                     result_inner.pushKV("fees", std::move(fees));
    1288         [ +  + ]:         653 :                     for (const auto& ptx : it->second.m_replaced_transactions) {
    1289         [ +  - ]:         383 :                         replaced_txids.insert(ptx->GetHash());
    1290                 :             :                     }
    1291                 :         270 :                     break;
    1292                 :             :                 }
    1293   [ -  +  +  - ]:        1095 :                 tx_result_map.pushKV(wtxid_hex, std::move(result_inner));
    1294                 :         371 :             }
    1295   [ +  -  +  - ]:         224 :             rpc_result.pushKV("tx-results", std::move(tx_result_map));
    1296                 :         224 :             UniValue replaced_list(UniValue::VARR);
    1297   [ +  -  +  -  :         495 :             for (const auto& txid : replaced_txids) replaced_list.push_back(txid.ToString());
             +  -  +  + ]
    1298   [ +  -  +  - ]:         224 :             rpc_result.pushKV("replaced-transactions", std::move(replaced_list));
    1299                 :         224 :             return rpc_result;
    1300                 :         122 :         },
    1301   [ +  -  +  -  :       24810 :     };
          +  -  +  +  +  
             +  -  -  -  
                      - ]
    1302   [ +  -  +  -  :       54582 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  -  -  
             -  -  -  -  
                      - ]
    1303                 :             : 
    1304                 :        1307 : void RegisterMempoolRPCCommands(CRPCTable& t)
    1305                 :             : {
    1306                 :        1307 :     static const CRPCCommand commands[]{
    1307         [ +  - ]:        2352 :         {"rawtransactions", &sendrawtransaction},
    1308         [ +  - ]:        2352 :         {"rawtransactions", &testmempoolaccept},
    1309         [ +  - ]:        2352 :         {"blockchain", &getmempoolancestors},
    1310         [ +  - ]:        2352 :         {"blockchain", &getmempooldescendants},
    1311         [ +  - ]:        2352 :         {"blockchain", &getmempoolentry},
    1312         [ +  - ]:        2352 :         {"blockchain", &getmempoolcluster},
    1313         [ +  - ]:        2352 :         {"blockchain", &gettxspendingprevout},
    1314         [ +  - ]:        2352 :         {"blockchain", &getmempoolinfo},
    1315         [ +  - ]:        2352 :         {"hidden", &getmempoolfeeratediagram},
    1316         [ +  - ]:        2352 :         {"blockchain", &getrawmempool},
    1317         [ +  - ]:        2352 :         {"blockchain", &importmempool},
    1318         [ +  - ]:        2352 :         {"blockchain", &savemempool},
    1319         [ +  - ]:        2352 :         {"hidden", &getorphantxs},
    1320         [ +  - ]:        2352 :         {"rawtransactions", &submitpackage},
    1321   [ +  +  +  -  :       17771 :     };
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  -  
                      - ]
    1322         [ +  + ]:       19605 :     for (const auto& c : commands) {
    1323                 :       18298 :         t.appendCommand(c.name, &c);
    1324                 :             :     }
    1325                 :        1307 : }
        

Generated by: LCOV version 2.0-1