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