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