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