LCOV - code coverage report
Current view: top level - src/rpc - mempool.cpp (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 96.6 % 587 567
Test Date: 2024-07-04 05:05:02 Functions: 100.0 % 28 28
Branches: 51.2 % 2528 1294

             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 <core_io.h>
      12                 :             : #include <kernel/mempool_entry.h>
      13                 :             : #include <node/mempool_persist_args.h>
      14                 :             : #include <node/types.h>
      15                 :             : #include <policy/rbf.h>
      16                 :             : #include <policy/settings.h>
      17                 :             : #include <primitives/transaction.h>
      18                 :             : #include <rpc/server.h>
      19                 :             : #include <rpc/server_util.h>
      20                 :             : #include <rpc/util.h>
      21                 :             : #include <txmempool.h>
      22                 :             : #include <univalue.h>
      23                 :             : #include <util/fs.h>
      24                 :             : #include <util/moneystr.h>
      25                 :             : #include <util/strencodings.h>
      26                 :             : #include <util/time.h>
      27                 :             : 
      28                 :             : #include <utility>
      29                 :             : 
      30                 :             : using node::DumpMempool;
      31                 :             : 
      32                 :             : using node::DEFAULT_MAX_BURN_AMOUNT;
      33                 :             : using node::DEFAULT_MAX_RAW_TX_FEE_RATE;
      34                 :             : using node::MempoolPath;
      35                 :             : using node::NodeContext;
      36                 :             : using node::TransactionError;
      37                 :             : using util::ToString;
      38                 :             : 
      39                 :       22952 : static RPCHelpMan sendrawtransaction()
      40                 :             : {
      41                 :       22952 :     return RPCHelpMan{"sendrawtransaction",
      42                 :             :         "\nSubmit a raw transaction (serialized, hex-encoded) to local node and network.\n"
      43                 :             :         "\nThe transaction will be sent unconditionally to all peers, so using sendrawtransaction\n"
      44                 :             :         "for manual rebroadcast may degrade privacy by leaking the transaction's origin, as\n"
      45                 :             :         "nodes will normally not rebroadcast non-wallet transactions already in their mempool.\n"
      46                 :             :         "\nA specific exception, RPC_TRANSACTION_ALREADY_IN_CHAIN, may throw if the transaction cannot be added to the mempool.\n"
      47                 :             :         "\nRelated RPCs: createrawtransaction, signrawtransactionwithkey\n",
      48                 :             :         {
      49         [ +  - ]:       22952 :             {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex string of the raw transaction"},
      50   [ +  -  +  - ]:       45904 :             {"maxfeerate", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK())},
      51                 :       22952 :              "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT +
      52                 :             :                  "/kvB.\nFee rates larger than 1BTC/kvB are rejected.\nSet to 0 to accept any fee rate."},
      53   [ +  -  +  - ]:       45904 :             {"maxburnamount", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_BURN_AMOUNT)},
      54                 :       22952 :              "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"
      55                 :             :              "If burning funds through unspendable outputs is desired, increase this value.\n"
      56                 :             :              "This check is based on heuristics and does not guarantee spendability of outputs.\n"},
      57                 :             :         },
      58         [ +  - ]:       45904 :         RPCResult{
      59                 :             :             RPCResult::Type::STR_HEX, "", "The transaction hash in hex"
      60   [ +  -  +  -  :       22952 :         },
                   +  - ]
      61         [ +  - ]:       45904 :         RPCExamples{
      62                 :             :             "\nCreate a transaction\n"
      63   [ +  -  +  -  :       45904 :             + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") +
             +  -  +  - ]
      64                 :             :             "Sign the transaction, and get back the hex\n"
      65   [ +  -  +  -  :       91808 :             + HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
             +  -  +  - ]
      66                 :             :             "\nSend the transaction (signed hex)\n"
      67   [ +  -  +  -  :       91808 :             + HelpExampleCli("sendrawtransaction", "\"signedhex\"") +
             +  -  +  - ]
      68                 :             :             "\nAs a JSON-RPC call\n"
      69   [ +  -  +  -  :       91808 :             + HelpExampleRpc("sendrawtransaction", "\"signedhex\"")
             +  -  +  - ]
      70                 :             :                 },
      71                 :       20536 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
      72                 :             :         {
      73         [ +  + ]:       20536 :             const CAmount max_burn_amount = request.params[2].isNull() ? 0 : AmountFromValue(request.params[2]);
      74                 :             : 
      75                 :       20536 :             CMutableTransaction mtx;
      76   [ +  -  +  -  :       20536 :             if (!DecodeHexTx(mtx, request.params[0].get_str())) {
             +  -  +  + ]
      77   [ +  -  +  - ]:           4 :                 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input.");
      78                 :             :             }
      79                 :             : 
      80         [ +  + ]:       89843 :             for (const auto& out : mtx.vout) {
      81   [ +  +  +  -  :       69313 :                 if((out.scriptPubKey.IsUnspendable() || !out.scriptPubKey.HasValidOps()) && out.nValue > max_burn_amount) {
             +  +  +  + ]
      82   [ +  -  +  - ]:           8 :                     throw JSONRPCTransactionError(TransactionError::MAX_BURN_EXCEEDED);
      83                 :             :                 }
      84                 :             :             }
      85                 :             : 
      86         [ +  - ]:       20530 :             CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
      87                 :             : 
      88   [ +  -  +  - ]:       20530 :             const CFeeRate max_raw_tx_fee_rate{ParseFeeRate(self.Arg<UniValue>("maxfeerate"))};
      89                 :             : 
      90         [ +  - ]:       20530 :             int64_t virtual_size = GetVirtualTransactionSize(*tx);
      91         [ +  - ]:       20530 :             CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size);
      92                 :             : 
      93         [ +  - ]:       20530 :             std::string err_string;
      94                 :       20530 :             AssertLockNotHeld(cs_main);
      95         [ +  - ]:       20530 :             NodeContext& node = EnsureAnyNodeContext(request.context);
      96   [ +  -  +  -  :       41060 :             const TransactionError err = BroadcastTransaction(node, tx, err_string, max_raw_tx_fee, /*relay=*/true, /*wait_callback=*/true);
                   +  - ]
      97         [ +  + ]:       20530 :             if (TransactionError::OK != err) {
      98         [ +  - ]:        4245 :                 throw JSONRPCTransactionError(err, err_string);
      99                 :             :             }
     100                 :             : 
     101   [ +  -  +  - ]:       32570 :             return tx->GetHash().GetHex();
     102         [ +  - ]:       57345 :         },
     103   [ +  -  +  -  :      298376 :     };
          +  -  +  -  +  
          -  +  -  +  -  
             +  +  -  - ]
     104   [ +  -  +  -  :      275424 : }
          +  -  +  -  +  
          -  +  -  +  -  
                   -  - ]
     105                 :             : 
     106                 :        3802 : static RPCHelpMan testmempoolaccept()
     107                 :             : {
     108                 :        3802 :     return RPCHelpMan{"testmempoolaccept",
     109                 :             :         "\nReturns result of mempool acceptance tests indicating if raw transaction(s) (serialized, hex-encoded) would be accepted by mempool.\n"
     110                 :             :         "\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"
     111                 :             :         "\nIf one transaction fails, other transactions may not be fully validated (the 'allowed' key will be blank).\n"
     112   [ +  -  +  - ]:        7604 :         "\nThe maximum number of transactions allowed is " + ToString(MAX_PACKAGE_COUNT) + ".\n"
     113                 :             :         "\nThis checks if transactions violate the consensus or policy rules.\n"
     114                 :             :         "\nSee sendrawtransaction call.\n",
     115                 :             :         {
     116         [ +  - ]:        3802 :             {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of hex strings of raw transactions.",
     117                 :             :                 {
     118         [ +  - ]:        3802 :                     {"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
     119                 :             :                 },
     120                 :             :             },
     121   [ +  -  +  - ]:        7604 :             {"maxfeerate", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK())},
     122                 :        3802 :              "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT +
     123                 :             :                  "/kvB.\nFee rates larger than 1BTC/kvB are rejected.\nSet to 0 to accept any fee rate."},
     124                 :             :         },
     125   [ +  -  +  -  :       15208 :         RPCResult{
             +  +  -  - ]
     126                 :             :             RPCResult::Type::ARR, "", "The result of the mempool acceptance test for each raw transaction in the input array.\n"
     127                 :             :                                       "Returns results for each transaction in the same order they were passed in.\n"
     128                 :             :                                       "Transactions that cannot be fully validated due to failures in other transactions will not contain an 'allowed' result.\n",
     129                 :             :             {
     130                 :             :                 {RPCResult::Type::OBJ, "", "",
     131                 :             :                 {
     132                 :             :                     {RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
     133                 :             :                     {RPCResult::Type::STR_HEX, "wtxid", "The transaction witness hash in hex"},
     134                 :             :                     {RPCResult::Type::STR, "package-error", /*optional=*/true, "Package validation error, if any (only possible if rawtxs had more than 1 transaction)."},
     135                 :             :                     {RPCResult::Type::BOOL, "allowed", /*optional=*/true, "Whether this tx would be accepted to the mempool and pass client-specified maxfeerate. "
     136                 :             :                                                        "If not present, the tx was not fully validated due to a failure in another tx in the list."},
     137                 :             :                     {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)"},
     138                 :             :                     {RPCResult::Type::OBJ, "fees", /*optional=*/true, "Transaction fees (only present if 'allowed' is true)",
     139                 :             :                     {
     140         [ +  - ]:        7604 :                         {RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT},
     141         [ +  - ]:        7604 :                         {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."},
     142                 :             :                         {RPCResult::Type::ARR, "effective-includes", /*optional=*/false, "transactions whose fees and vsizes are included in effective-feerate.",
     143   [ +  -  +  -  :        3802 :                             {RPCResult{RPCResult::Type::STR_HEX, "", "transaction wtxid in hex"},
                   +  - ]
     144                 :             :                         }},
     145                 :             :                     }},
     146                 :             :                     {RPCResult::Type::STR, "reject-reason", /*optional=*/true, "Rejection string (only present when 'allowed' is false)"},
     147                 :             :                 }},
     148                 :             :             }
     149   [ +  -  +  -  :       60832 :         },
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     150         [ +  - ]:        7604 :         RPCExamples{
     151                 :             :             "\nCreate a transaction\n"
     152   [ +  -  +  -  :        7604 :             + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") +
             +  -  +  - ]
     153                 :             :             "Sign the transaction, and get back the hex\n"
     154   [ +  -  +  -  :       15208 :             + HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
             +  -  +  - ]
     155                 :             :             "\nTest acceptance of the transaction (signed hex)\n"
     156   [ +  -  +  -  :       15208 :             + HelpExampleCli("testmempoolaccept", R"('["signedhex"]')") +
             +  -  +  - ]
     157                 :             :             "\nAs a JSON-RPC call\n"
     158   [ +  -  +  -  :       15208 :             + HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]")
             +  -  +  - ]
     159                 :             :                 },
     160                 :        1386 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     161                 :             :         {
     162                 :        1386 :             const UniValue raw_transactions = request.params[0].get_array();
     163   [ +  +  +  + ]:        1386 :             if (raw_transactions.size() < 1 || raw_transactions.size() > MAX_PACKAGE_COUNT) {
     164                 :           2 :                 throw JSONRPCError(RPC_INVALID_PARAMETER,
     165   [ +  -  +  -  :           6 :                                    "Array must contain between 1 and " + ToString(MAX_PACKAGE_COUNT) + " transactions.");
                   +  - ]
     166                 :             :             }
     167                 :             : 
     168   [ +  -  +  + ]:        1384 :             const CFeeRate max_raw_tx_fee_rate{ParseFeeRate(self.Arg<UniValue>("maxfeerate"))};
     169                 :             : 
     170                 :        1382 :             std::vector<CTransactionRef> txns;
     171         [ +  - ]:        1382 :             txns.reserve(raw_transactions.size());
     172   [ +  -  +  + ]:        3365 :             for (const auto& rawtx : raw_transactions.getValues()) {
     173         [ +  - ]:        1984 :                 CMutableTransaction mtx;
     174   [ +  -  +  -  :        1984 :                 if (!DecodeHexTx(mtx, rawtx.get_str())) {
                   +  + ]
     175                 :           1 :                     throw JSONRPCError(RPC_DESERIALIZATION_ERROR,
     176   [ +  -  +  -  :           3 :                                        "TX decode failed: " + rawtx.get_str() + " Make sure the tx has at least one input.");
                   +  - ]
     177                 :             :                 }
     178   [ +  -  +  - ]:        5949 :                 txns.emplace_back(MakeTransactionRef(std::move(mtx)));
     179                 :        1984 :             }
     180                 :             : 
     181         [ +  - ]:        1381 :             NodeContext& node = EnsureAnyNodeContext(request.context);
     182         [ +  - ]:        1381 :             CTxMemPool& mempool = EnsureMemPool(node);
     183         [ +  - ]:        1381 :             ChainstateManager& chainman = EnsureChainman(node);
     184         [ +  - ]:        1381 :             Chainstate& chainstate = chainman.ActiveChainstate();
     185                 :        2762 :             const PackageMempoolAcceptResult package_result = [&] {
     186                 :        1381 :                 LOCK(::cs_main);
     187   [ +  +  +  - ]:        1381 :                 if (txns.size() > 1) return ProcessNewPackage(chainstate, mempool, txns, /*test_accept=*/true, /*client_maxfeerate=*/{});
     188         [ +  - ]:        1298 :                 return PackageMempoolAcceptResult(txns[0]->GetWitnessHash(),
     189   [ +  -  +  - ]:        1298 :                                                   chainman.ProcessTransaction(txns[0], /*test_accept=*/true));
     190         [ +  - ]:        2762 :             }();
     191                 :             : 
     192                 :        1381 :             UniValue rpc_result(UniValue::VARR);
     193                 :             :             // We will check transaction fees while we iterate through txns in order. If any transaction fee
     194                 :             :             // exceeds maxfeerate, we will leave the rest of the validation results blank, because it
     195                 :             :             // doesn't make sense to return a validation result for a transaction if its ancestor(s) would
     196                 :             :             // not be submitted.
     197                 :        1381 :             bool exit_early{false};
     198         [ +  + ]:        3364 :             for (const auto& tx : txns) {
     199                 :        1983 :                 UniValue result_inner(UniValue::VOBJ);
     200   [ +  -  +  -  :        3966 :                 result_inner.pushKV("txid", tx->GetHash().GetHex());
             +  -  +  - ]
     201   [ +  -  +  -  :        3966 :                 result_inner.pushKV("wtxid", tx->GetWitnessHash().GetHex());
             +  -  +  - ]
     202         [ +  + ]:        1983 :                 if (package_result.m_state.GetResult() == PackageValidationResult::PCKG_POLICY) {
     203   [ +  -  +  -  :         220 :                     result_inner.pushKV("package-error", package_result.m_state.ToString());
             +  -  +  - ]
     204                 :             :                 }
     205                 :        1983 :                 auto it = package_result.m_tx_results.find(tx->GetWitnessHash());
     206   [ +  +  +  + ]:        1983 :                 if (exit_early || it == package_result.m_tx_results.end()) {
     207                 :             :                     // Validation unfinished. Just return the txid and wtxid.
     208         [ +  - ]:         150 :                     rpc_result.push_back(std::move(result_inner));
     209                 :         150 :                     continue;
     210                 :             :                 }
     211         [ +  - ]:        1833 :                 const auto& tx_result = it->second;
     212                 :             :                 // Package testmempoolaccept doesn't allow transactions to already be in the mempool.
     213         [ +  - ]:        1833 :                 CHECK_NONFATAL(tx_result.m_result_type != MempoolAcceptResult::ResultType::MEMPOOL_ENTRY);
     214         [ +  + ]:        1833 :                 if (tx_result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
     215         [ +  - ]:        1701 :                     const CAmount fee = tx_result.m_base_fees.value();
     216                 :             :                     // Check that fee does not exceed maximum fee
     217         [ +  - ]:        1701 :                     const int64_t virtual_size = tx_result.m_vsize.value();
     218         [ +  - ]:        1701 :                     const CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size);
     219         [ +  + ]:        1701 :                     if (max_raw_tx_fee && fee > max_raw_tx_fee) {
     220   [ +  -  +  -  :           8 :                         result_inner.pushKV("allowed", false);
                   +  - ]
     221   [ +  -  +  -  :           4 :                         result_inner.pushKV("reject-reason", "max-fee-exceeded");
                   +  - ]
     222                 :           4 :                         exit_early = true;
     223                 :             :                     } else {
     224                 :             :                         // Only return the fee and vsize if the transaction would pass ATMP.
     225                 :             :                         // These can be used to calculate the feerate.
     226   [ +  -  +  -  :        3394 :                         result_inner.pushKV("allowed", true);
                   +  - ]
     227   [ +  -  +  -  :        3394 :                         result_inner.pushKV("vsize", virtual_size);
                   +  - ]
     228                 :        1697 :                         UniValue fees(UniValue::VOBJ);
     229   [ +  -  +  -  :        3394 :                         fees.pushKV("base", ValueFromAmount(fee));
                   +  - ]
     230   [ +  -  +  -  :        3394 :                         fees.pushKV("effective-feerate", ValueFromAmount(tx_result.m_effective_feerate.value().GetFeePerK()));
             +  -  +  - ]
     231                 :        1697 :                         UniValue effective_includes_res(UniValue::VARR);
     232   [ +  -  +  + ]:        3394 :                         for (const auto& wtxid : tx_result.m_wtxids_fee_calculations.value()) {
     233   [ +  -  +  -  :        1697 :                             effective_includes_res.push_back(wtxid.ToString());
                   +  - ]
     234                 :             :                         }
     235   [ +  -  +  - ]:        3394 :                         fees.pushKV("effective-includes", std::move(effective_includes_res));
     236   [ +  -  +  - ]:        3394 :                         result_inner.pushKV("fees", std::move(fees));
     237                 :        1697 :                     }
     238                 :             :                 } else {
     239   [ +  -  +  -  :         264 :                     result_inner.pushKV("allowed", false);
                   +  - ]
     240         [ +  - ]:         132 :                     const TxValidationState state = tx_result.m_state;
     241         [ +  + ]:         132 :                     if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
     242   [ +  -  +  -  :          12 :                         result_inner.pushKV("reject-reason", "missing-inputs");
                   +  - ]
     243                 :             :                     } else {
     244   [ +  -  +  -  :         252 :                         result_inner.pushKV("reject-reason", state.GetRejectReason());
             +  -  +  - ]
     245                 :             :                     }
     246                 :         132 :                 }
     247         [ +  - ]:        1833 :                 rpc_result.push_back(std::move(result_inner));
     248                 :        1983 :             }
     249                 :        1381 :             return rpc_result;
     250                 :        1387 :         },
     251   [ +  -  +  -  :       53228 :     };
          +  -  +  -  +  
          -  +  -  +  +  
                   -  - ]
     252   [ +  -  +  -  :      129268 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          +  +  +  +  +  
          +  +  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
                      - ]
     253                 :             : 
     254                 :       18688 : static std::vector<RPCResult> MempoolEntryDescription()
     255                 :             : {
     256                 :       18688 :     return {
     257   [ +  -  +  -  :       18688 :         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."},
                   +  - ]
     258   [ +  -  +  -  :       18688 :         RPCResult{RPCResult::Type::NUM, "weight", "transaction weight as defined in BIP 141."},
                   +  - ]
     259   [ +  -  +  -  :       18688 :         RPCResult{RPCResult::Type::NUM_TIME, "time", "local time transaction entered pool in seconds since 1 Jan 1970 GMT"},
                   +  - ]
     260   [ +  -  +  -  :       18688 :         RPCResult{RPCResult::Type::NUM, "height", "block height when transaction entered pool"},
                   +  - ]
     261   [ +  -  +  -  :       18688 :         RPCResult{RPCResult::Type::NUM, "descendantcount", "number of in-mempool descendant transactions (including this one)"},
                   +  - ]
     262   [ +  -  +  -  :       18688 :         RPCResult{RPCResult::Type::NUM, "descendantsize", "virtual transaction size of in-mempool descendants (including this one)"},
                   +  - ]
     263   [ +  -  +  -  :       18688 :         RPCResult{RPCResult::Type::NUM, "ancestorcount", "number of in-mempool ancestor transactions (including this one)"},
                   +  - ]
     264   [ +  -  +  -  :       18688 :         RPCResult{RPCResult::Type::NUM, "ancestorsize", "virtual transaction size of in-mempool ancestors (including this one)"},
                   +  - ]
     265   [ +  -  +  -  :       18688 :         RPCResult{RPCResult::Type::STR_HEX, "wtxid", "hash of serialized transaction, including witness data"},
                   +  - ]
     266                 :             :         RPCResult{RPCResult::Type::OBJ, "fees", "",
     267                 :             :             {
     268   [ +  -  +  -  :       37376 :                 RPCResult{RPCResult::Type::STR_AMOUNT, "base", "transaction fee, denominated in " + CURRENCY_UNIT},
                   +  - ]
     269   [ +  -  +  -  :       37376 :                 RPCResult{RPCResult::Type::STR_AMOUNT, "modified", "transaction fee with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT},
                   +  - ]
     270   [ +  -  +  -  :       37376 :                 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},
                   +  - ]
     271   [ +  -  +  -  :       37376 :                 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},
                   +  - ]
     272   [ +  -  +  - ]:       93440 :             }},
     273                 :             :         RPCResult{RPCResult::Type::ARR, "depends", "unconfirmed transactions used as inputs for this transaction",
     274   [ +  -  +  -  :       37376 :             {RPCResult{RPCResult::Type::STR_HEX, "transactionid", "parent transaction id"}}},
          +  -  +  -  +  
                      - ]
     275                 :             :         RPCResult{RPCResult::Type::ARR, "spentby", "unconfirmed transactions spending outputs from this transaction",
     276   [ +  -  +  -  :       37376 :             {RPCResult{RPCResult::Type::STR_HEX, "transactionid", "child transaction id"}}},
          +  -  +  -  +  
                      - ]
     277   [ +  -  +  -  :       18688 :         RPCResult{RPCResult::Type::BOOL, "bip125-replaceable", "Whether this transaction signals BIP125 replaceability or has an unconfirmed ancestor signaling BIP125 replaceability.\n"},
                   +  - ]
     278   [ +  -  +  -  :       18688 :         RPCResult{RPCResult::Type::BOOL, "unbroadcast", "Whether this transaction is currently unbroadcast (initial broadcast not yet acknowledged by any peers)"},
                   +  - ]
     279   [ +  -  +  +  :      299008 :     };
                   -  - ]
     280   [ +  -  +  -  :      541952 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          +  +  +  +  +  
          -  -  -  -  -  
             -  -  -  -  
                      - ]
     281                 :             : 
     282                 :        4144 : static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPoolEntry& e) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
     283                 :             : {
     284                 :        4144 :     AssertLockHeld(pool.cs);
     285                 :             : 
     286   [ +  -  +  - ]:        8288 :     info.pushKV("vsize", (int)e.GetTxSize());
     287   [ +  -  +  - ]:        8288 :     info.pushKV("weight", (int)e.GetTxWeight());
     288   [ +  -  +  - ]:        8288 :     info.pushKV("time", count_seconds(e.GetTime()));
     289   [ +  -  +  - ]:        8288 :     info.pushKV("height", (int)e.GetHeight());
     290   [ +  -  +  - ]:        8288 :     info.pushKV("descendantcount", e.GetCountWithDescendants());
     291   [ +  -  +  - ]:        8288 :     info.pushKV("descendantsize", e.GetSizeWithDescendants());
     292   [ +  -  +  - ]:        8288 :     info.pushKV("ancestorcount", e.GetCountWithAncestors());
     293   [ +  -  +  - ]:        8288 :     info.pushKV("ancestorsize", e.GetSizeWithAncestors());
     294   [ +  -  +  -  :        8288 :     info.pushKV("wtxid", e.GetTx().GetWitnessHash().ToString());
                   +  - ]
     295                 :             : 
     296                 :        4144 :     UniValue fees(UniValue::VOBJ);
     297   [ +  -  +  -  :        8288 :     fees.pushKV("base", ValueFromAmount(e.GetFee()));
                   +  - ]
     298   [ +  -  +  -  :        8288 :     fees.pushKV("modified", ValueFromAmount(e.GetModifiedFee()));
                   +  - ]
     299   [ +  -  +  -  :        8288 :     fees.pushKV("ancestor", ValueFromAmount(e.GetModFeesWithAncestors()));
                   +  - ]
     300   [ +  -  +  -  :        8288 :     fees.pushKV("descendant", ValueFromAmount(e.GetModFeesWithDescendants()));
                   +  - ]
     301   [ +  -  +  - ]:        8288 :     info.pushKV("fees", std::move(fees));
     302                 :             : 
     303                 :        4144 :     const CTransaction& tx = e.GetTx();
     304                 :        4144 :     std::set<std::string> setDepends;
     305         [ +  + ]:       14132 :     for (const CTxIn& txin : tx.vin)
     306                 :             :     {
     307   [ +  -  +  + ]:        9988 :         if (pool.exists(GenTxid::Txid(txin.prevout.hash)))
     308   [ +  -  +  - ]:       12308 :             setDepends.insert(txin.prevout.hash.ToString());
     309                 :             :     }
     310                 :             : 
     311                 :        4144 :     UniValue depends(UniValue::VARR);
     312         [ +  + ]:       10298 :     for (const std::string& dep : setDepends)
     313                 :             :     {
     314   [ +  -  +  - ]:        6154 :         depends.push_back(dep);
     315                 :             :     }
     316                 :             : 
     317   [ +  -  +  - ]:        8288 :     info.pushKV("depends", std::move(depends));
     318                 :             : 
     319                 :        4144 :     UniValue spent(UniValue::VARR);
     320   [ +  -  +  + ]:       10105 :     for (const CTxMemPoolEntry& child : e.GetMemPoolChildrenConst()) {
     321   [ +  -  +  -  :        5961 :         spent.push_back(child.GetTx().GetHash().ToString());
                   +  - ]
     322                 :             :     }
     323                 :             : 
     324   [ +  -  +  - ]:        8288 :     info.pushKV("spentby", std::move(spent));
     325                 :             : 
     326                 :             :     // Add opt-in RBF status
     327                 :        4144 :     bool rbfStatus = false;
     328         [ +  - ]:        4144 :     RBFTransactionState rbfState = IsRBFOptIn(tx, pool);
     329         [ -  + ]:        4144 :     if (rbfState == RBFTransactionState::UNKNOWN) {
     330   [ #  #  #  # ]:           0 :         throw JSONRPCError(RPC_MISC_ERROR, "Transaction is not in mempool");
     331         [ +  + ]:        4144 :     } else if (rbfState == RBFTransactionState::REPLACEABLE_BIP125) {
     332                 :        3152 :         rbfStatus = true;
     333                 :             :     }
     334                 :             : 
     335   [ +  -  +  -  :        8288 :     info.pushKV("bip125-replaceable", rbfStatus);
                   +  - ]
     336   [ +  -  +  -  :        8288 :     info.pushKV("unbroadcast", pool.IsUnbroadcastTx(tx.GetHash()));
                   +  - ]
     337                 :        4144 : }
     338                 :             : 
     339                 :        8092 : UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose, bool include_mempool_sequence)
     340                 :             : {
     341         [ +  + ]:        8092 :     if (verbose) {
     342         [ +  + ]:         866 :         if (include_mempool_sequence) {
     343   [ +  -  +  - ]:           2 :             throw JSONRPCError(RPC_INVALID_PARAMETER, "Verbose results cannot contain mempool sequence values.");
     344                 :             :         }
     345                 :         865 :         LOCK(pool.cs);
     346                 :         865 :         UniValue o(UniValue::VOBJ);
     347   [ +  -  +  + ]:        3532 :         for (const CTxMemPoolEntry& e : pool.entryAll()) {
     348                 :        2667 :             UniValue info(UniValue::VOBJ);
     349         [ +  - ]:        2667 :             entryToJSON(pool, info, e);
     350                 :             :             // Mempool has unique entries so there is no advantage in using
     351                 :             :             // UniValue::pushKV, which checks if the key already exists in O(N).
     352                 :             :             // UniValue::pushKVEnd is used instead which currently is O(1).
     353   [ +  -  +  - ]:        5334 :             o.pushKVEnd(e.GetTx().GetHash().ToString(), std::move(info));
     354                 :        2667 :         }
     355                 :         865 :         return o;
     356         [ +  - ]:        1730 :     } else {
     357                 :        7226 :         UniValue a(UniValue::VARR);
     358                 :        7226 :         uint64_t mempool_sequence;
     359                 :        7226 :         {
     360         [ +  - ]:        7226 :             LOCK(pool.cs);
     361   [ +  -  +  -  :      219132 :             for (const CTxMemPoolEntry& e : pool.entryAll()) {
                   +  + ]
     362   [ +  -  +  -  :      211906 :                 a.push_back(e.GetTx().GetHash().ToString());
                   +  - ]
     363                 :           0 :             }
     364         [ +  - ]:        7226 :             mempool_sequence = pool.GetSequence();
     365                 :           0 :         }
     366         [ +  + ]:        7226 :         if (!include_mempool_sequence) {
     367                 :        7219 :             return a;
     368                 :             :         } else {
     369                 :           7 :             UniValue o(UniValue::VOBJ);
     370   [ +  -  +  - ]:          14 :             o.pushKV("txids", std::move(a));
     371   [ +  -  +  -  :          14 :             o.pushKV("mempool_sequence", mempool_sequence);
                   +  - ]
     372                 :           7 :             return o;
     373                 :           7 :         }
     374                 :        7226 :     }
     375                 :             : }
     376                 :             : 
     377                 :       10503 : static RPCHelpMan getrawmempool()
     378                 :             : {
     379                 :       10503 :     return RPCHelpMan{"getrawmempool",
     380                 :             :         "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"
     381                 :             :         "\nHint: use getmempoolentry to fetch a specific transaction from the mempool.\n",
     382                 :             :         {
     383         [ +  - ]:       21006 :             {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "True for a json object, false for array of transaction ids"},
     384         [ +  - ]:       21006 :             {"mempool_sequence", RPCArg::Type::BOOL, RPCArg::Default{false}, "If verbose=false, returns a json object with transaction list and mempool sequence number attached."},
     385                 :             :         },
     386                 :             :         {
     387                 :             :             RPCResult{"for verbose = false",
     388                 :             :                 RPCResult::Type::ARR, "", "",
     389                 :             :                 {
     390                 :             :                     {RPCResult::Type::STR_HEX, "", "The transaction id"},
     391   [ +  -  +  -  :       21006 :                 }},
          +  -  +  -  +  
                -  +  - ]
     392                 :             :             RPCResult{"for verbose = true",
     393                 :             :                 RPCResult::Type::OBJ_DYN, "", "",
     394                 :             :                 {
     395         [ +  - ]:       21006 :                     {RPCResult::Type::OBJ, "transactionid", "", MempoolEntryDescription()},
     396   [ +  -  +  -  :       21006 :                 }},
          +  -  +  -  +  
                      - ]
     397                 :             :             RPCResult{"for verbose = false and mempool_sequence = true",
     398                 :             :                 RPCResult::Type::OBJ, "", "",
     399                 :             :                 {
     400                 :             :                     {RPCResult::Type::ARR, "txids", "",
     401                 :             :                     {
     402                 :             :                         {RPCResult::Type::STR_HEX, "", "The transaction id"},
     403                 :             :                     }},
     404                 :             :                     {RPCResult::Type::NUM, "mempool_sequence", "The mempool sequence value."},
     405   [ +  -  +  -  :       52515 :                 }},
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     406                 :             :         },
     407         [ +  - ]:       21006 :         RPCExamples{
     408   [ +  -  +  -  :       21006 :             HelpExampleCli("getrawmempool", "true")
                   +  - ]
     409   [ +  -  +  -  :       42012 :             + HelpExampleRpc("getrawmempool", "true")
             +  -  +  - ]
     410                 :             :         },
     411                 :        8088 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     412                 :             : {
     413                 :        8088 :     bool fVerbose = false;
     414         [ +  + ]:        8088 :     if (!request.params[0].isNull())
     415                 :         898 :         fVerbose = request.params[0].get_bool();
     416                 :             : 
     417                 :        8088 :     bool include_mempool_sequence = false;
     418         [ +  + ]:        8088 :     if (!request.params[1].isNull()) {
     419                 :           8 :         include_mempool_sequence = request.params[1].get_bool();
     420                 :             :     }
     421                 :             : 
     422                 :        8088 :     return MempoolToJSON(EnsureAnyMemPool(request.context), fVerbose, include_mempool_sequence);
     423                 :             : },
     424   [ +  -  +  -  :      157545 :     };
          +  -  +  -  +  
          -  +  -  +  -  
          +  +  +  +  -  
                -  -  - ]
     425   [ +  -  +  -  :      199557 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  +  +  
          +  +  +  +  +  
          -  -  -  -  -  
          -  -  -  -  -  
             -  -  -  - ]
     426                 :             : 
     427                 :        2466 : static RPCHelpMan getmempoolancestors()
     428                 :             : {
     429                 :        2466 :     return RPCHelpMan{"getmempoolancestors",
     430                 :             :         "\nIf txid is in the mempool, returns all in-mempool ancestors.\n",
     431                 :             :         {
     432         [ +  - ]:        2466 :             {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"},
     433         [ +  - ]:        4932 :             {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "True for a json object, false for array of transaction ids"},
     434                 :             :         },
     435                 :             :         {
     436                 :             :             RPCResult{"for verbose = false",
     437                 :             :                 RPCResult::Type::ARR, "", "",
     438   [ +  -  +  -  :        4932 :                 {{RPCResult::Type::STR_HEX, "", "The transaction id of an in-mempool ancestor transaction"}}},
          +  -  +  -  +  
                -  +  - ]
     439                 :             :             RPCResult{"for verbose = true",
     440                 :             :                 RPCResult::Type::OBJ_DYN, "", "",
     441                 :             :                 {
     442         [ +  - ]:        4932 :                     {RPCResult::Type::OBJ, "transactionid", "", MempoolEntryDescription()},
     443   [ +  -  +  -  :        4932 :                 }},
          +  -  +  -  +  
                      - ]
     444                 :             :         },
     445         [ +  - ]:        4932 :         RPCExamples{
     446   [ +  -  +  -  :        4932 :             HelpExampleCli("getmempoolancestors", "\"mytxid\"")
                   +  - ]
     447   [ +  -  +  -  :        9864 :             + HelpExampleRpc("getmempoolancestors", "\"mytxid\"")
             +  -  +  - ]
     448                 :             :         },
     449                 :          51 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     450                 :             : {
     451                 :          51 :     bool fVerbose = false;
     452         [ +  + ]:          51 :     if (!request.params[1].isNull())
     453                 :          26 :         fVerbose = request.params[1].get_bool();
     454                 :             : 
     455                 :          51 :     uint256 hash = ParseHashV(request.params[0], "parameter 1");
     456                 :             : 
     457                 :          51 :     const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
     458                 :          51 :     LOCK(mempool.cs);
     459                 :             : 
     460         [ +  - ]:          51 :     const auto entry{mempool.GetEntry(Txid::FromUint256(hash))};
     461         [ -  + ]:          51 :     if (entry == nullptr) {
     462   [ #  #  #  # ]:           0 :         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool");
     463                 :             :     }
     464                 :             : 
     465         [ +  - ]:          51 :     auto ancestors{mempool.AssumeCalculateMemPoolAncestors(self.m_name, *entry, CTxMemPool::Limits::NoLimits(), /*fSearchForParents=*/false)};
     466                 :             : 
     467         [ +  + ]:          51 :     if (!fVerbose) {
     468                 :          25 :         UniValue o(UniValue::VARR);
     469         [ +  + ]:         325 :         for (CTxMemPool::txiter ancestorIt : ancestors) {
     470   [ +  -  +  -  :         300 :             o.push_back(ancestorIt->GetTx().GetHash().ToString());
                   +  - ]
     471                 :             :         }
     472                 :          25 :         return o;
     473                 :          25 :     } else {
     474                 :          26 :         UniValue o(UniValue::VOBJ);
     475         [ +  + ]:         350 :         for (CTxMemPool::txiter ancestorIt : ancestors) {
     476                 :         324 :             const CTxMemPoolEntry &e = *ancestorIt;
     477                 :         324 :             const uint256& _hash = e.GetTx().GetHash();
     478                 :         324 :             UniValue info(UniValue::VOBJ);
     479         [ +  - ]:         324 :             entryToJSON(mempool, info, e);
     480   [ +  -  +  - ]:         648 :             o.pushKV(_hash.ToString(), std::move(info));
     481                 :         324 :         }
     482                 :          26 :         return o;
     483                 :          26 :     }
     484         [ +  - ]:         102 : },
     485   [ +  -  +  -  :       34524 :     };
          +  -  +  -  +  
          -  +  -  +  -  
          +  +  +  +  -  
                -  -  - ]
     486   [ +  -  +  -  :       29592 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  +  +  +  -  
          -  -  -  -  -  
                   -  - ]
     487                 :             : 
     488                 :        2466 : static RPCHelpMan getmempooldescendants()
     489                 :             : {
     490                 :        2466 :     return RPCHelpMan{"getmempooldescendants",
     491                 :             :         "\nIf txid is in the mempool, returns all in-mempool descendants.\n",
     492                 :             :         {
     493         [ +  - ]:        2466 :             {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"},
     494         [ +  - ]:        4932 :             {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "True for a json object, false for array of transaction ids"},
     495                 :             :         },
     496                 :             :         {
     497                 :             :             RPCResult{"for verbose = false",
     498                 :             :                 RPCResult::Type::ARR, "", "",
     499   [ +  -  +  -  :        4932 :                 {{RPCResult::Type::STR_HEX, "", "The transaction id of an in-mempool descendant transaction"}}},
          +  -  +  -  +  
                -  +  - ]
     500                 :             :             RPCResult{"for verbose = true",
     501                 :             :                 RPCResult::Type::OBJ_DYN, "", "",
     502                 :             :                 {
     503         [ +  - ]:        4932 :                     {RPCResult::Type::OBJ, "transactionid", "", MempoolEntryDescription()},
     504   [ +  -  +  -  :        4932 :                 }},
          +  -  +  -  +  
                      - ]
     505                 :             :         },
     506         [ +  - ]:        4932 :         RPCExamples{
     507   [ +  -  +  -  :        4932 :             HelpExampleCli("getmempooldescendants", "\"mytxid\"")
                   +  - ]
     508   [ +  -  +  -  :        9864 :             + HelpExampleRpc("getmempooldescendants", "\"mytxid\"")
             +  -  +  - ]
     509                 :             :         },
     510                 :          51 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     511                 :             : {
     512                 :          51 :     bool fVerbose = false;
     513         [ +  + ]:          51 :     if (!request.params[1].isNull())
     514                 :          26 :         fVerbose = request.params[1].get_bool();
     515                 :             : 
     516                 :          51 :     uint256 hash = ParseHashV(request.params[0], "parameter 1");
     517                 :             : 
     518                 :          51 :     const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
     519                 :          51 :     LOCK(mempool.cs);
     520                 :             : 
     521         [ +  - ]:          51 :     const auto it{mempool.GetIter(hash)};
     522         [ -  + ]:          51 :     if (!it) {
     523   [ #  #  #  # ]:           0 :         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool");
     524                 :             :     }
     525                 :             : 
     526         [ +  - ]:          51 :     CTxMemPool::setEntries setDescendants;
     527         [ +  - ]:          51 :     mempool.CalculateDescendants(*it, setDescendants);
     528                 :             :     // CTxMemPool::CalculateDescendants will include the given tx
     529                 :          51 :     setDescendants.erase(*it);
     530                 :             : 
     531         [ +  + ]:          51 :     if (!fVerbose) {
     532                 :          25 :         UniValue o(UniValue::VARR);
     533         [ +  + ]:         325 :         for (CTxMemPool::txiter descendantIt : setDescendants) {
     534   [ +  -  +  -  :         300 :             o.push_back(descendantIt->GetTx().GetHash().ToString());
                   +  - ]
     535                 :             :         }
     536                 :             : 
     537                 :          25 :         return o;
     538                 :          25 :     } else {
     539                 :          26 :         UniValue o(UniValue::VOBJ);
     540         [ +  + ]:         350 :         for (CTxMemPool::txiter descendantIt : setDescendants) {
     541                 :         324 :             const CTxMemPoolEntry &e = *descendantIt;
     542                 :         324 :             const uint256& _hash = e.GetTx().GetHash();
     543                 :         324 :             UniValue info(UniValue::VOBJ);
     544         [ +  - ]:         324 :             entryToJSON(mempool, info, e);
     545   [ +  -  +  - ]:         648 :             o.pushKV(_hash.ToString(), std::move(info));
     546                 :         324 :         }
     547                 :          26 :         return o;
     548                 :          26 :     }
     549         [ +  - ]:         102 : },
     550   [ +  -  +  -  :       34524 :     };
          +  -  +  -  +  
          -  +  -  +  -  
          +  +  +  +  -  
                -  -  - ]
     551   [ +  -  +  -  :       29592 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  +  +  +  -  
          -  -  -  -  -  
                   -  - ]
     552                 :             : 
     553                 :        3253 : static RPCHelpMan getmempoolentry()
     554                 :             : {
     555                 :        3253 :     return RPCHelpMan{"getmempoolentry",
     556                 :             :         "\nReturns mempool data for given transaction\n",
     557                 :             :         {
     558         [ +  - ]:        3253 :             {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"},
     559                 :             :         },
     560         [ +  - ]:        6506 :         RPCResult{
     561   [ +  -  +  -  :        6506 :             RPCResult::Type::OBJ, "", "", MempoolEntryDescription()},
                   +  - ]
     562         [ +  - ]:        6506 :         RPCExamples{
     563   [ +  -  +  -  :        6506 :             HelpExampleCli("getmempoolentry", "\"mytxid\"")
                   +  - ]
     564   [ +  -  +  -  :       13012 :             + HelpExampleRpc("getmempoolentry", "\"mytxid\"")
             +  -  +  - ]
     565                 :             :         },
     566                 :         838 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     567                 :             : {
     568                 :         838 :     uint256 hash = ParseHashV(request.params[0], "parameter 1");
     569                 :             : 
     570                 :         838 :     const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
     571                 :         838 :     LOCK(mempool.cs);
     572                 :             : 
     573         [ +  - ]:         838 :     const auto entry{mempool.GetEntry(Txid::FromUint256(hash))};
     574         [ +  + ]:         838 :     if (entry == nullptr) {
     575   [ +  -  +  - ]:          18 :         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool");
     576                 :             :     }
     577                 :             : 
     578                 :         829 :     UniValue info(UniValue::VOBJ);
     579         [ +  - ]:         829 :     entryToJSON(mempool, info, *entry);
     580         [ +  - ]:         829 :     return info;
     581                 :         829 : },
     582   [ +  -  +  -  :       29277 :     };
          +  -  +  -  +  
             -  +  +  -  
                      - ]
     583   [ +  -  +  -  :        6506 : }
                   +  - ]
     584                 :             : 
     585                 :        2451 : static RPCHelpMan gettxspendingprevout()
     586                 :             : {
     587                 :        2451 :     return RPCHelpMan{"gettxspendingprevout",
     588                 :             :         "Scans the mempool to find transactions spending any of the given outputs",
     589                 :             :         {
     590         [ +  - ]:        2451 :             {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The transaction outputs that we want to check, and within each, the txid (string) vout (numeric).",
     591                 :             :                 {
     592         [ +  - ]:        2451 :                     {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
     593                 :             :                         {
     594         [ +  - ]:        2451 :                             {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
     595         [ +  - ]:        2451 :                             {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
     596                 :             :                         },
     597                 :             :                     },
     598                 :             :                 },
     599                 :             :             },
     600                 :             :         },
     601   [ +  -  +  -  :        9804 :         RPCResult{
             +  +  -  - ]
     602                 :             :             RPCResult::Type::ARR, "", "",
     603                 :             :             {
     604                 :             :                 {RPCResult::Type::OBJ, "", "",
     605                 :             :                 {
     606                 :             :                     {RPCResult::Type::STR_HEX, "txid", "the transaction id of the checked output"},
     607                 :             :                     {RPCResult::Type::NUM, "vout", "the vout value of the checked output"},
     608                 :             :                     {RPCResult::Type::STR_HEX, "spendingtxid", /*optional=*/true, "the transaction id of the mempool transaction spending this output (omitted if unspent)"},
     609                 :             :                 }},
     610                 :             :             }
     611   [ +  -  +  -  :       12255 :         },
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     612         [ +  - ]:        4902 :         RPCExamples{
     613   [ +  -  +  -  :        4902 :             HelpExampleCli("gettxspendingprevout", "\"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":3}]\"")
                   +  - ]
     614   [ +  -  +  -  :        9804 :             + HelpExampleRpc("gettxspendingprevout", "\"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":3}]\"")
             +  -  +  - ]
     615                 :             :         },
     616                 :          36 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     617                 :             :         {
     618                 :          36 :             const UniValue& output_params = request.params[0].get_array();
     619         [ +  + ]:          36 :             if (output_params.empty()) {
     620   [ +  -  +  - ]:           2 :                 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, outputs are missing");
     621                 :             :             }
     622                 :             : 
     623                 :          35 :             std::vector<COutPoint> prevouts;
     624         [ +  - ]:          35 :             prevouts.reserve(output_params.size());
     625                 :             : 
     626         [ +  + ]:          68 :             for (unsigned int idx = 0; idx < output_params.size(); idx++) {
     627   [ +  -  +  - ]:          38 :                 const UniValue& o = output_params[idx].get_obj();
     628                 :             : 
     629   [ +  +  +  +  :         156 :                 RPCTypeCheckObj(o,
                   +  + ]
     630                 :             :                                 {
     631         [ +  - ]:          38 :                                     {"txid", UniValueType(UniValue::VSTR)},
     632         [ +  - ]:          38 :                                     {"vout", UniValueType(UniValue::VNUM)},
     633                 :             :                                 }, /*fAllowNull=*/false, /*fStrict=*/true);
     634                 :             : 
     635         [ +  - ]:          34 :                 const Txid txid = Txid::FromUint256(ParseHashO(o, "txid"));
     636   [ +  -  +  - ]:          34 :                 const int nOutput{o.find_value("vout").getInt<int>()};
     637         [ +  + ]:          34 :                 if (nOutput < 0) {
     638   [ +  -  +  - ]:           2 :                     throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout cannot be negative");
     639                 :             :                 }
     640                 :             : 
     641         [ +  - ]:          33 :                 prevouts.emplace_back(txid, nOutput);
     642                 :             :             }
     643                 :             : 
     644         [ +  - ]:          30 :             const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
     645         [ +  - ]:          30 :             LOCK(mempool.cs);
     646                 :             : 
     647                 :          30 :             UniValue result{UniValue::VARR};
     648                 :             : 
     649         [ +  + ]:          63 :             for (const COutPoint& prevout : prevouts) {
     650                 :          33 :                 UniValue o(UniValue::VOBJ);
     651   [ +  -  +  -  :          66 :                 o.pushKV("txid", prevout.hash.ToString());
             +  -  +  - ]
     652   [ +  -  +  -  :          66 :                 o.pushKV("vout", (uint64_t)prevout.n);
                   +  - ]
     653                 :             : 
     654         [ +  - ]:          33 :                 const CTransaction* spendingTx = mempool.GetConflictTx(prevout);
     655         [ +  + ]:          33 :                 if (spendingTx != nullptr) {
     656   [ +  -  +  -  :          60 :                     o.pushKV("spendingtxid", spendingTx->GetHash().ToString());
             +  -  +  - ]
     657                 :             :                 }
     658                 :             : 
     659         [ +  - ]:          33 :                 result.push_back(std::move(o));
     660                 :          33 :             }
     661                 :             : 
     662         [ +  - ]:          60 :             return result;
     663   [ +  -  +  -  :          77 :         },
             +  -  -  + ]
     664   [ +  -  +  -  :       36765 :     };
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  +  -  
                      - ]
     665   [ +  -  +  -  :       46569 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  +  +  +  +  
          +  -  -  -  -  
          -  -  -  -  -  
                      - ]
     666                 :             : 
     667                 :        2187 : UniValue MempoolInfoToJSON(const CTxMemPool& pool)
     668                 :             : {
     669                 :             :     // Make sure this call is atomic in the pool.
     670                 :        2187 :     LOCK(pool.cs);
     671                 :        2187 :     UniValue ret(UniValue::VOBJ);
     672   [ +  -  +  -  :        4374 :     ret.pushKV("loaded", pool.GetLoadTried());
             +  -  +  - ]
     673   [ +  -  +  -  :        4374 :     ret.pushKV("size", (int64_t)pool.size());
             +  -  +  - ]
     674   [ +  -  +  -  :        4374 :     ret.pushKV("bytes", (int64_t)pool.GetTotalTxSize());
                   +  - ]
     675   [ +  -  +  -  :        4374 :     ret.pushKV("usage", (int64_t)pool.DynamicMemoryUsage());
             +  -  +  - ]
     676   [ +  -  +  -  :        4374 :     ret.pushKV("total_fee", ValueFromAmount(pool.GetTotalFee()));
                   +  - ]
     677   [ +  -  +  -  :        4374 :     ret.pushKV("maxmempool", pool.m_opts.max_size_bytes);
                   +  - ]
     678   [ +  -  +  +  :        6495 :     ret.pushKV("mempoolminfee", ValueFromAmount(std::max(pool.GetMinFee(), pool.m_opts.min_relay_feerate).GetFeePerK()));
          +  -  +  -  +  
                      - ]
     679   [ +  -  +  -  :        4374 :     ret.pushKV("minrelaytxfee", ValueFromAmount(pool.m_opts.min_relay_feerate.GetFeePerK()));
                   +  - ]
     680   [ +  -  +  -  :        4374 :     ret.pushKV("incrementalrelayfee", ValueFromAmount(pool.m_opts.incremental_relay_feerate.GetFeePerK()));
                   +  - ]
     681   [ +  -  +  -  :        4374 :     ret.pushKV("unbroadcastcount", uint64_t{pool.GetUnbroadcastTxs().size()});
             +  -  +  - ]
     682   [ +  -  +  -  :        4374 :     ret.pushKV("fullrbf", pool.m_opts.full_rbf);
                   +  - ]
     683         [ +  - ]:        2187 :     return ret;
     684                 :        2187 : }
     685                 :             : 
     686                 :        4601 : static RPCHelpMan getmempoolinfo()
     687                 :             : {
     688                 :        4601 :     return RPCHelpMan{"getmempoolinfo",
     689                 :             :         "Returns details on the active state of the TX memory pool.",
     690                 :             :         {},
     691   [ +  -  +  -  :       64414 :         RPCResult{
             +  +  -  - ]
     692                 :             :             RPCResult::Type::OBJ, "", "",
     693                 :             :             {
     694                 :             :                 {RPCResult::Type::BOOL, "loaded", "True if the initial load attempt of the persisted mempool finished"},
     695                 :             :                 {RPCResult::Type::NUM, "size", "Current tx count"},
     696                 :             :                 {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"},
     697                 :             :                 {RPCResult::Type::NUM, "usage", "Total memory usage for the mempool"},
     698         [ +  - ]:        9202 :                 {RPCResult::Type::STR_AMOUNT, "total_fee", "Total fees for the mempool in " + CURRENCY_UNIT + ", ignoring modified fees through prioritisetransaction"},
     699                 :             :                 {RPCResult::Type::NUM, "maxmempool", "Maximum memory usage for the mempool"},
     700         [ +  - ]:        9202 :                 {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"},
     701                 :             :                 {RPCResult::Type::STR_AMOUNT, "minrelaytxfee", "Current minimum relay fee for transactions"},
     702         [ +  - ]:        9202 :                 {RPCResult::Type::NUM, "incrementalrelayfee", "minimum fee rate increment for mempool limiting or replacement in " + CURRENCY_UNIT + "/kvB"},
     703                 :             :                 {RPCResult::Type::NUM, "unbroadcastcount", "Current number of transactions that haven't passed initial broadcast yet"},
     704                 :             :                 {RPCResult::Type::BOOL, "fullrbf", "True if the mempool accepts RBF without replaceability signaling inspection"},
     705   [ +  -  +  -  :       69015 :             }},
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     706         [ +  - ]:        9202 :         RPCExamples{
     707   [ +  -  +  -  :        9202 :             HelpExampleCli("getmempoolinfo", "")
                   +  - ]
     708   [ +  -  +  -  :       18404 :             + HelpExampleRpc("getmempoolinfo", "")
             +  -  +  - ]
     709                 :             :         },
     710                 :        2186 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     711                 :             : {
     712                 :        2186 :     return MempoolInfoToJSON(EnsureAnyMemPool(request.context));
     713                 :             : },
     714   [ +  -  +  -  :       27606 :     };
             +  -  +  - ]
     715   [ +  -  +  -  :       73616 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   -  - ]
     716                 :             : 
     717                 :        2418 : static RPCHelpMan importmempool()
     718                 :             : {
     719                 :        2418 :     return RPCHelpMan{
     720                 :             :         "importmempool",
     721                 :             :         "Import a mempool.dat file and attempt to add its contents to the mempool.\n"
     722                 :             :         "Warning: Importing untrusted files is dangerous, especially if metadata from the file is taken over.",
     723                 :             :         {
     724         [ +  - ]:        2418 :             {"filepath", RPCArg::Type::STR, RPCArg::Optional::NO, "The mempool file"},
     725                 :             :             {"options",
     726                 :             :              RPCArg::Type::OBJ_NAMED_PARAMS,
     727         [ +  - ]:        2418 :              RPCArg::Optional::OMITTED,
     728                 :             :              "",
     729                 :             :              {
     730         [ +  - ]:        4836 :                  {"use_current_time", RPCArg::Type::BOOL, RPCArg::Default{true},
     731                 :             :                   "Whether to use the current system time or use the entry time metadata from the mempool file.\n"
     732                 :             :                   "Warning: Importing untrusted metadata may lead to unexpected issues and undesirable behavior."},
     733         [ +  - ]:        4836 :                  {"apply_fee_delta_priority", RPCArg::Type::BOOL, RPCArg::Default{false},
     734                 :             :                   "Whether to apply the fee delta metadata from the mempool file.\n"
     735                 :             :                   "It will be added to any existing fee deltas.\n"
     736                 :             :                   "The fee delta can be set by the prioritisetransaction RPC.\n"
     737                 :             :                   "Warning: Importing untrusted metadata may lead to unexpected issues and undesirable behavior.\n"
     738                 :             :                   "Only set this bool if you understand what it does."},
     739         [ +  - ]:        4836 :                  {"apply_unbroadcast_set", RPCArg::Type::BOOL, RPCArg::Default{false},
     740                 :             :                   "Whether to apply the unbroadcast set metadata from the mempool file.\n"
     741                 :             :                   "Warning: Importing untrusted metadata may lead to unexpected issues and undesirable behavior."},
     742                 :             :              },
     743   [ +  -  +  - ]:        2418 :              RPCArgOptions{.oneline_description = "options"}},
     744                 :             :         },
     745   [ +  -  +  -  :        4836 :         RPCResult{RPCResult::Type::OBJ, "", "", std::vector<RPCResult>{}},
                   +  - ]
     746   [ +  -  +  -  :        7254 :         RPCExamples{HelpExampleCli("importmempool", "/path/to/mempool.dat") + HelpExampleRpc("importmempool", "/path/to/mempool.dat")},
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     747                 :           3 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
     748                 :           3 :             const NodeContext& node{EnsureAnyNodeContext(request.context)};
     749                 :             : 
     750                 :           3 :             CTxMemPool& mempool{EnsureMemPool(node)};
     751                 :           3 :             ChainstateManager& chainman = EnsureChainman(node);
     752                 :           3 :             Chainstate& chainstate = chainman.ActiveChainstate();
     753                 :             : 
     754         [ -  + ]:           3 :             if (chainman.IsInitialBlockDownload()) {
     755   [ #  #  #  # ]:           0 :                 throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Can only import the mempool after the block download and sync is done.");
     756                 :             :             }
     757                 :             : 
     758                 :           3 :             const fs::path load_path{fs::u8path(request.params[0].get_str())};
     759   [ +  -  +  -  :           3 :             const UniValue& use_current_time{request.params[1]["use_current_time"]};
                   +  - ]
     760   [ +  -  +  -  :           3 :             const UniValue& apply_fee_delta{request.params[1]["apply_fee_delta_priority"]};
                   +  - ]
     761   [ +  -  +  -  :           3 :             const UniValue& apply_unbroadcast{request.params[1]["apply_unbroadcast_set"]};
                   +  - ]
     762         [ -  + ]:           3 :             node::ImportMempoolOptions opts{
     763   [ -  +  -  - ]:           3 :                 .use_current_time = use_current_time.isNull() ? true : use_current_time.get_bool(),
     764   [ +  +  +  - ]:           3 :                 .apply_fee_delta_priority = apply_fee_delta.isNull() ? false : apply_fee_delta.get_bool(),
     765   [ +  +  +  - ]:           3 :                 .apply_unbroadcast_set = apply_unbroadcast.isNull() ? false : apply_unbroadcast.get_bool(),
     766   [ -  +  +  +  :           5 :             };
                   +  + ]
     767                 :             : 
     768   [ +  -  -  + ]:           3 :             if (!node::LoadMempool(mempool, load_path, chainstate, std::move(opts))) {
     769   [ #  #  #  # ]:           0 :                 throw JSONRPCError(RPC_MISC_ERROR, "Unable to import mempool file, see debug.log for details.");
     770                 :             :             }
     771                 :             : 
     772                 :           3 :             UniValue ret{UniValue::VOBJ};
     773                 :           3 :             return ret;
     774                 :           6 :         },
     775   [ +  -  +  -  :       41106 :     };
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                +  -  - ]
     776   [ +  -  +  -  :       41106 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  +  -  -  -  
                -  -  - ]
     777                 :             : 
     778                 :        2419 : static RPCHelpMan savemempool()
     779                 :             : {
     780                 :        2419 :     return RPCHelpMan{"savemempool",
     781                 :             :         "\nDumps the mempool to disk. It will fail until the previous dump is fully loaded.\n",
     782                 :             :         {},
     783   [ +  -  +  -  :        9676 :         RPCResult{
             +  +  -  - ]
     784                 :             :             RPCResult::Type::OBJ, "", "",
     785                 :             :             {
     786                 :             :                 {RPCResult::Type::STR, "filename", "the directory and file where the mempool was saved"},
     787   [ +  -  +  -  :        4838 :             }},
          +  -  +  -  +  
                      - ]
     788         [ +  - ]:        4838 :         RPCExamples{
     789   [ +  -  +  -  :        4838 :             HelpExampleCli("savemempool", "")
                   +  - ]
     790   [ +  -  +  -  :        9676 :             + HelpExampleRpc("savemempool", "")
             +  -  +  - ]
     791                 :             :         },
     792                 :           4 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     793                 :             : {
     794                 :           4 :     const ArgsManager& args{EnsureAnyArgsman(request.context)};
     795                 :           4 :     const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
     796                 :             : 
     797         [ -  + ]:           4 :     if (!mempool.GetLoadTried()) {
     798   [ #  #  #  # ]:           0 :         throw JSONRPCError(RPC_MISC_ERROR, "The mempool was not loaded yet");
     799                 :             :     }
     800                 :             : 
     801                 :           4 :     const fs::path& dump_path = MempoolPath(args);
     802                 :             : 
     803   [ +  -  +  + ]:           4 :     if (!DumpMempool(mempool, dump_path)) {
     804   [ +  -  +  - ]:           2 :         throw JSONRPCError(RPC_MISC_ERROR, "Unable to dump mempool to disk");
     805                 :             :     }
     806                 :             : 
     807                 :           3 :     UniValue ret(UniValue::VOBJ);
     808   [ +  -  +  -  :           6 :     ret.pushKV("filename", dump_path.utf8string());
             +  -  +  - ]
     809                 :             : 
     810                 :           3 :     return ret;
     811                 :           3 : },
     812   [ +  -  +  -  :       14514 :     };
             +  -  +  - ]
     813   [ +  -  +  - ]:        7257 : }
     814                 :             : 
     815                 :        2482 : static RPCHelpMan submitpackage()
     816                 :             : {
     817                 :        2482 :     return RPCHelpMan{"submitpackage",
     818                 :             :         "Submit a package of raw transactions (serialized, hex-encoded) to local node.\n"
     819                 :             :         "The package will be validated according to consensus and mempool policy rules. If any transaction passes, it will be accepted to mempool.\n"
     820                 :             :         "This RPC is experimental and the interface may be unstable. Refer to doc/policy/packages.md for documentation on package policies.\n"
     821                 :             :         "Warning: successful submission does not mean the transactions will propagate throughout the network.\n"
     822                 :             :         ,
     823                 :             :         {
     824         [ +  - ]:        2482 :             {"package", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of raw transactions.\n"
     825                 :             :                 "The package must solely consist of a child and its parents. None of the parents may depend on each other.\n"
     826                 :             :                 "The package must be topologically sorted, with the child being the last element in the array.",
     827                 :             :                 {
     828         [ +  - ]:        2482 :                     {"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
     829                 :             :                 },
     830                 :             :             },
     831   [ +  -  +  - ]:        4964 :             {"maxfeerate", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK())},
     832                 :        2482 :              "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT +
     833                 :             :                  "/kvB.\nFee rates larger than 1BTC/kvB are rejected.\nSet to 0 to accept any fee rate."},
     834   [ +  -  +  - ]:        4964 :             {"maxburnamount", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_BURN_AMOUNT)},
     835                 :        2482 :              "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"
     836                 :             :              "If burning funds through unspendable outputs is desired, increase this value.\n"
     837                 :             :              "This check is based on heuristics and does not guarantee spendability of outputs.\n"
     838                 :             :             },
     839                 :             :         },
     840   [ +  -  +  -  :       14892 :         RPCResult{
             +  +  -  - ]
     841                 :             :             RPCResult::Type::OBJ, "", "",
     842                 :             :             {
     843                 :             :                 {RPCResult::Type::STR, "package_msg", "The transaction package result message. \"success\" indicates all transactions were accepted into or are already in the mempool."},
     844                 :             :                 {RPCResult::Type::OBJ_DYN, "tx-results", "transaction results keyed by wtxid",
     845                 :             :                 {
     846                 :             :                     {RPCResult::Type::OBJ, "wtxid", "transaction wtxid", {
     847                 :             :                         {RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
     848                 :             :                         {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."},
     849                 :             :                         {RPCResult::Type::NUM, "vsize", /*optional=*/true, "Sigops-adjusted virtual transaction size."},
     850                 :             :                         {RPCResult::Type::OBJ, "fees", /*optional=*/true, "Transaction fees", {
     851         [ +  - ]:        4964 :                             {RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT},
     852         [ +  - ]:        4964 :                             {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."},
     853                 :             :                             {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.",
     854                 :             :                                 {{RPCResult::Type::STR_HEX, "", "transaction wtxid in hex"},
     855                 :             :                             }},
     856                 :             :                         }},
     857                 :             :                         {RPCResult::Type::STR, "error", /*optional=*/true, "The transaction error string, if it was rejected by the mempool"},
     858                 :             :                     }}
     859                 :             :                 }},
     860                 :             :                 {RPCResult::Type::ARR, "replaced-transactions", /*optional=*/true, "List of txids of replaced transactions",
     861                 :             :                 {
     862                 :             :                     {RPCResult::Type::STR_HEX, "", "The transaction id"},
     863                 :             :                 }},
     864                 :             :             },
     865   [ +  -  +  -  :       47158 :         },
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     866         [ +  - ]:        4964 :         RPCExamples{
     867   [ +  -  +  -  :        4964 :             HelpExampleRpc("submitpackage", R"(["rawtx1", "rawtx2"])") +
             +  -  +  - ]
     868   [ +  -  +  -  :        4964 :             HelpExampleCli("submitpackage", R"('["rawtx1", "rawtx2"]')")
                   +  - ]
     869                 :             :         },
     870                 :          67 :         [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
     871                 :             :         {
     872                 :          67 :             const UniValue raw_transactions = request.params[0].get_array();
     873   [ +  +  +  + ]:          67 :             if (raw_transactions.size() < 2 || raw_transactions.size() > MAX_PACKAGE_COUNT) {
     874                 :           3 :                 throw JSONRPCError(RPC_INVALID_PARAMETER,
     875   [ +  -  +  -  :           9 :                                    "Array must contain between 2 and " + ToString(MAX_PACKAGE_COUNT) + " transactions.");
                   +  - ]
     876                 :             :             }
     877                 :             : 
     878                 :             :             // Fee check needs to be run with chainstate and package context
     879   [ +  -  +  - ]:          64 :             const CFeeRate max_raw_tx_fee_rate{ParseFeeRate(self.Arg<UniValue>("maxfeerate"))};
     880         [ +  + ]:          64 :             std::optional<CFeeRate> client_maxfeerate{max_raw_tx_fee_rate};
     881                 :             :             // 0-value is special; it's mapped to no sanity check
     882         [ +  + ]:          64 :             if (max_raw_tx_fee_rate == CFeeRate(0)) {
     883                 :           4 :                 client_maxfeerate = std::nullopt;
     884                 :             :             }
     885                 :             : 
     886                 :             :             // Burn sanity check is run with no context
     887   [ +  -  +  +  :          64 :             const CAmount max_burn_amount = request.params[2].isNull() ? 0 : AmountFromValue(request.params[2]);
             +  -  +  - ]
     888                 :             : 
     889                 :          64 :             std::vector<CTransactionRef> txns;
     890         [ +  - ]:          64 :             txns.reserve(raw_transactions.size());
     891   [ +  -  +  + ]:         251 :             for (const auto& rawtx : raw_transactions.getValues()) {
     892         [ +  - ]:         188 :                 CMutableTransaction mtx;
     893   [ +  -  +  -  :         188 :                 if (!DecodeHexTx(mtx, rawtx.get_str())) {
                   -  + ]
     894                 :           0 :                     throw JSONRPCError(RPC_DESERIALIZATION_ERROR,
     895   [ #  #  #  #  :           0 :                                        "TX decode failed: " + rawtx.get_str() + " Make sure the tx has at least one input.");
                   #  # ]
     896                 :             :                 }
     897                 :             : 
     898         [ +  + ]:         400 :                 for (const auto& out : mtx.vout) {
     899   [ +  +  +  -  :         213 :                     if((out.scriptPubKey.IsUnspendable() || !out.scriptPubKey.HasValidOps()) && out.nValue > max_burn_amount) {
             -  +  +  + ]
     900   [ +  -  +  - ]:           2 :                         throw JSONRPCTransactionError(TransactionError::MAX_BURN_EXCEEDED);
     901                 :             :                     }
     902                 :             :                 }
     903                 :             : 
     904   [ +  -  +  - ]:         561 :                 txns.emplace_back(MakeTransactionRef(std::move(mtx)));
     905                 :         188 :             }
     906   [ +  -  +  + ]:          63 :             if (!IsChildWithParentsTree(txns)) {
     907   [ +  -  +  - ]:           2 :                 throw JSONRPCTransactionError(TransactionError::INVALID_PACKAGE, "package topology disallowed. not child-with-parents or parents depend on each other.");
     908                 :             :             }
     909                 :             : 
     910         [ +  - ]:          62 :             NodeContext& node = EnsureAnyNodeContext(request.context);
     911         [ +  - ]:          62 :             CTxMemPool& mempool = EnsureMemPool(node);
     912   [ +  -  +  - ]:          62 :             Chainstate& chainstate = EnsureChainman(node).ActiveChainstate();
     913   [ +  -  +  - ]:         186 :             const auto package_result = WITH_LOCK(::cs_main, return ProcessNewPackage(chainstate, mempool, txns, /*test_accept=*/ false, client_maxfeerate));
     914                 :             : 
     915         [ +  - ]:          62 :             std::string package_msg = "success";
     916                 :             : 
     917                 :             :             // First catch package-wide errors, continue if we can
     918   [ +  -  +  - ]:          62 :             switch(package_result.m_state.GetResult()) {
     919                 :          24 :                 case PackageValidationResult::PCKG_RESULT_UNSET:
     920                 :          24 :                 {
     921                 :             :                     // Belt-and-suspenders check; everything should be successful here
     922         [ +  - ]:          24 :                     CHECK_NONFATAL(package_result.m_tx_results.size() == txns.size());
     923         [ +  + ]:         122 :                     for (const auto& tx : txns) {
     924   [ +  -  +  - ]:          98 :                         CHECK_NONFATAL(mempool.exists(GenTxid::Txid(tx->GetHash())));
     925                 :             :                     }
     926                 :             :                     break;
     927                 :             :                 }
     928                 :           0 :                 case PackageValidationResult::PCKG_MEMPOOL_ERROR:
     929                 :           0 :                 {
     930                 :             :                     // This only happens with internal bug; user should stop and report
     931                 :           0 :                     throw JSONRPCTransactionError(TransactionError::MEMPOOL_ERROR,
     932   [ #  #  #  # ]:           0 :                         package_result.m_state.GetRejectReason());
     933                 :             :                 }
     934                 :          38 :                 case PackageValidationResult::PCKG_POLICY:
     935                 :          38 :                 case PackageValidationResult::PCKG_TX:
     936                 :          38 :                 {
     937                 :             :                     // Package-wide error we want to return, but we also want to return individual responses
     938         [ +  - ]:          38 :                     package_msg = package_result.m_state.ToString();
     939   [ +  +  +  -  :          42 :                     CHECK_NONFATAL(package_result.m_tx_results.size() == txns.size() ||
                   +  - ]
     940                 :             :                             package_result.m_tx_results.empty());
     941                 :             :                     break;
     942                 :             :                 }
     943                 :             :             }
     944                 :             : 
     945                 :          62 :             size_t num_broadcast{0};
     946         [ +  + ]:         245 :             for (const auto& tx : txns) {
     947                 :             :                 // We don't want to re-submit the txn for validation in BroadcastTransaction
     948   [ +  -  +  + ]:         183 :                 if (!mempool.exists(GenTxid::Txid(tx->GetHash()))) {
     949                 :          74 :                     continue;
     950                 :             :                 }
     951                 :             : 
     952                 :             :                 // We do not expect an error here; we are only broadcasting things already/still in mempool
     953         [ +  - ]:         109 :                 std::string err_string;
     954   [ +  -  +  -  :         218 :                 const auto err = BroadcastTransaction(node, tx, err_string, /*max_tx_fee=*/0, /*relay=*/true, /*wait_callback=*/true);
                   +  - ]
     955         [ -  + ]:         109 :                 if (err != TransactionError::OK) {
     956                 :           0 :                     throw JSONRPCTransactionError(err,
     957         [ #  # ]:           0 :                         strprintf("transaction broadcast failed: %s (%d transactions were broadcast successfully)",
     958         [ #  # ]:           0 :                             err_string, num_broadcast));
     959                 :             :                 }
     960                 :         109 :                 num_broadcast++;
     961                 :         109 :             }
     962                 :             : 
     963                 :          62 :             UniValue rpc_result{UniValue::VOBJ};
     964   [ +  -  +  -  :         124 :             rpc_result.pushKV("package_msg", package_msg);
                   +  - ]
     965                 :         124 :             UniValue tx_result_map{UniValue::VOBJ};
     966                 :         124 :             std::set<uint256> replaced_txids;
     967         [ +  + ]:         245 :             for (const auto& tx : txns) {
     968                 :         183 :                 UniValue result_inner{UniValue::VOBJ};
     969   [ +  -  +  -  :         366 :                 result_inner.pushKV("txid", tx->GetHash().GetHex());
             +  -  +  - ]
     970                 :         183 :                 auto it = package_result.m_tx_results.find(tx->GetWitnessHash());
     971         [ +  + ]:         183 :                 if (it == package_result.m_tx_results.end()) {
     972                 :             :                     // No results, report error and continue
     973   [ +  -  +  -  :          20 :                     result_inner.pushKV("error", "unevaluated");
                   +  - ]
     974                 :          10 :                     continue;
     975                 :             :                 }
     976   [ -  +  +  - ]:         173 :                 const auto& tx_result = it->second;
     977   [ -  +  +  - ]:         173 :                 switch(it->second.m_result_type) {
     978                 :           0 :                 case MempoolAcceptResult::ResultType::DIFFERENT_WITNESS:
     979   [ #  #  #  #  :           0 :                     result_inner.pushKV("other-wtxid", it->second.m_other_wtxid.value().GetHex());
          #  #  #  #  #  
                      # ]
     980                 :           0 :                     break;
     981                 :          65 :                 case MempoolAcceptResult::ResultType::INVALID:
     982   [ +  -  +  -  :         130 :                     result_inner.pushKV("error", it->second.m_state.ToString());
             +  -  +  - ]
     983                 :          65 :                     break;
     984                 :         108 :                 case MempoolAcceptResult::ResultType::VALID:
     985                 :         108 :                 case MempoolAcceptResult::ResultType::MEMPOOL_ENTRY:
     986   [ +  -  +  -  :         216 :                     result_inner.pushKV("vsize", int64_t{it->second.m_vsize.value()});
             +  -  +  - ]
     987                 :         108 :                     UniValue fees(UniValue::VOBJ);
     988   [ +  -  +  -  :         216 :                     fees.pushKV("base", ValueFromAmount(it->second.m_base_fees.value()));
             +  -  +  - ]
     989         [ +  + ]:         108 :                     if (tx_result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
     990                 :             :                         // Effective feerate is not provided for MEMPOOL_ENTRY transactions even
     991                 :             :                         // though modified fees is known, because it is unknown whether package
     992                 :             :                         // feerate was used when it was originally submitted.
     993   [ +  -  +  -  :         182 :                         fees.pushKV("effective-feerate", ValueFromAmount(tx_result.m_effective_feerate.value().GetFeePerK()));
             +  -  +  - ]
     994                 :          91 :                         UniValue effective_includes_res(UniValue::VARR);
     995   [ +  -  +  + ]:         198 :                         for (const auto& wtxid : tx_result.m_wtxids_fee_calculations.value()) {
     996   [ +  -  +  -  :         107 :                             effective_includes_res.push_back(wtxid.ToString());
                   +  - ]
     997                 :             :                         }
     998   [ +  -  +  - ]:         182 :                         fees.pushKV("effective-includes", std::move(effective_includes_res));
     999                 :          91 :                     }
    1000   [ +  -  +  - ]:         216 :                     result_inner.pushKV("fees", std::move(fees));
    1001         [ +  + ]:         217 :                     for (const auto& ptx : it->second.m_replaced_transactions) {
    1002         [ +  - ]:         109 :                         replaced_txids.insert(ptx->GetHash());
    1003                 :             :                     }
    1004                 :         108 :                     break;
    1005                 :             :                 }
    1006   [ +  -  +  - ]:         346 :                 tx_result_map.pushKV(tx->GetWitnessHash().GetHex(), std::move(result_inner));
    1007                 :         183 :             }
    1008   [ +  -  +  - ]:         124 :             rpc_result.pushKV("tx-results", std::move(tx_result_map));
    1009                 :         124 :             UniValue replaced_list(UniValue::VARR);
    1010   [ +  -  +  -  :         171 :             for (const uint256& hash : replaced_txids) replaced_list.push_back(hash.ToString());
             +  -  +  + ]
    1011   [ +  -  +  - ]:         124 :             rpc_result.pushKV("replaced-transactions", std::move(replaced_list));
    1012                 :         124 :             return rpc_result;
    1013                 :          69 :         },
    1014   [ +  -  +  -  :       37230 :     };
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  +  -  
                      - ]
    1015   [ +  -  +  -  :       96798 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  +  +  +  
          +  +  +  +  +  
          +  +  +  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
                -  -  - ]
    1016                 :             : 
    1017                 :        1325 : void RegisterMempoolRPCCommands(CRPCTable& t)
    1018                 :             : {
    1019                 :        1325 :     static const CRPCCommand commands[]{
    1020                 :             :         {"rawtransactions", &sendrawtransaction},
    1021                 :             :         {"rawtransactions", &testmempoolaccept},
    1022                 :             :         {"blockchain", &getmempoolancestors},
    1023                 :             :         {"blockchain", &getmempooldescendants},
    1024                 :             :         {"blockchain", &getmempoolentry},
    1025                 :             :         {"blockchain", &gettxspendingprevout},
    1026                 :             :         {"blockchain", &getmempoolinfo},
    1027                 :             :         {"blockchain", &getrawmempool},
    1028                 :             :         {"blockchain", &importmempool},
    1029                 :             :         {"blockchain", &savemempool},
    1030                 :             :         {"rawtransactions", &submitpackage},
    1031   [ +  +  +  -  :        1325 :     };
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  -  
                      - ]
    1032         [ +  + ]:       15900 :     for (const auto& c : commands) {
    1033                 :       14575 :         t.appendCommand(c.name, &c);
    1034                 :             :     }
    1035                 :        1325 : }
        

Generated by: LCOV version 2.0-1