mempool.cpp raw

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