Bitcoin ABC 0.33.11
P2P Digital Currency
mempool.cpp
Go to the documentation of this file.
1// Copyright (c) 2010 Satoshi Nakamoto
2// Copyright (c) 2009-2022 The Bitcoin Core developers
3// Distributed under the MIT software license, see the accompanying
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
8
9#include <chainparams.h>
10#include <core_io.h>
11#include <node/context.h>
13#include <node/types.h>
14#include <policy/settings.h>
16#include <rpc/server.h>
17#include <rpc/server_util.h>
18#include <rpc/util.h>
19#include <txmempool.h>
20#include <univalue.h>
21#include <util/fs.h>
22#include <util/moneystr.h>
23#include <validation.h>
24#include <validationinterface.h>
25
27
32using util::ToString;
33
35 return RPCHelpMan{
36 "sendrawtransaction",
37 "Submits raw transaction (serialized, hex-encoded) to local node and "
38 "network.\n"
39 "\nAlso see createrawtransaction and "
40 "signrawtransactionwithkey calls.\n",
41 {
43 "The hex string of the raw transaction"},
44 {"maxfeerate", RPCArg::Type::AMOUNT,
47 "Reject transactions whose fee rate is higher than the specified "
48 "value, expressed in " +
50 "/kB\nSet to 0 to accept any fee rate.\n"},
51 },
52 RPCResult{RPCResult::Type::STR_HEX, "", "The transaction hash in hex"},
54 "\nCreate a transaction\n" +
56 "createrawtransaction",
57 "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" "
58 "\"{\\\"myaddress\\\":10000}\"") +
59 "Sign the transaction, and get back the hex\n" +
60 HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
61 "\nSend the transaction (signed hex)\n" +
62 HelpExampleCli("sendrawtransaction", "\"signedhex\"") +
63 "\nAs a JSON-RPC call\n" +
64 HelpExampleRpc("sendrawtransaction", "\"signedhex\"")},
65 [&](const RPCHelpMan &self, const Config &config,
66 const JSONRPCRequest &request) -> UniValue {
67 // parse hex string from parameter
69 if (!DecodeHexTx(mtx, request.params[0].get_str())) {
71 "TX decode failed");
72 }
73
74 CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
75
76 const CFeeRate max_raw_tx_fee_rate =
77 request.params[1].isNull()
79 : CFeeRate(AmountFromValue(request.params[1]));
80
81 int64_t virtual_size = GetVirtualTransactionSize(*tx);
82 Amount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size);
83
84 std::string err_string;
86 NodeContext &node = EnsureAnyNodeContext(request.context);
88 node, tx, err_string, max_raw_tx_fee, /*relay*/ true,
89 /*wait_callback*/ true);
90 if (err != TransactionError::OK) {
91 throw JSONRPCTransactionError(err, err_string);
92 }
93
94 // Block to make sure wallet/indexers sync before returning
95 CHECK_NONFATAL(node.validation_signals)
96 ->SyncWithValidationInterfaceQueue();
97
98 return tx->GetHash().GetHex();
99 },
100 };
101}
102
104 const auto ticker = Currency::getTicker();
105 return RPCHelpMan{
106 "testmempoolaccept",
107 "\nReturns result of mempool acceptance tests indicating if raw "
108 "transaction(s) (serialized, hex-encoded) would be accepted by "
109 "mempool.\n"
110 "\nIf multiple transactions are passed in, parents must come before "
111 "children and package policies apply: the transactions cannot conflict "
112 "with any mempool transactions or each other.\n"
113 "\nIf one transaction fails, other transactions may not be fully "
114 "validated (the 'allowed' key will be blank).\n"
115 "\nThe maximum number of transactions allowed is " +
117 ".\n"
118 "\nThis checks if transactions violate the consensus or policy "
119 "rules.\n"
120 "\nSee sendrawtransaction call.\n",
121 {
122 {
123 "rawtxs",
126 "An array of hex strings of raw transactions.",
127 {
129 ""},
130 },
131 },
132 {"maxfeerate", RPCArg::Type::AMOUNT,
135 "Reject transactions whose fee rate is higher than the specified "
136 "value, expressed in " +
137 ticker + "/kB\n"},
138 },
139 RPCResult{
141 "",
142 "The result of the mempool acceptance test for each raw "
143 "transaction in the input array.\n"
144 "Returns results for each transaction in the same order they were "
145 "passed in.\n"
146 "Transactions that cannot be fully validated due to failures in "
147 "other transactions will not contain an 'allowed' result.\n",
148 {
150 "",
151 "",
152 {
154 "The transaction hash in hex"},
155 {RPCResult::Type::STR, "package-error",
156 "Package validation error, if any (only possible if "
157 "rawtxs had more than 1 transaction)."},
158 {RPCResult::Type::BOOL, "allowed",
159 "Whether this tx would be accepted to the mempool and "
160 "pass client-specified maxfeerate. "
161 "If not present, the tx was not fully validated due to a "
162 "failure in another tx in the list."},
163 {RPCResult::Type::NUM, "size", "The transaction size"},
165 "fees",
166 "Transaction fees (only present if 'allowed' is true)",
167 {
169 "transaction fee in " + ticker},
170 {RPCResult::Type::STR_AMOUNT, "effective-feerate",
171 "the effective feerate in " + ticker +
172 " per KvB. May differ from the base feerate if, "
173 "for example, there are modified fees from "
174 "prioritisetransaction or a package feerate was "
175 "used."},
177 "effective-includes",
178 "transactions whose fees and vsizes are included in "
179 "effective-feerate.",
180 {
182 "transaction txid in hex"},
183 }},
184 }},
185 {RPCResult::Type::STR, "reject-reason", /*optional=*/true,
186 "Rejection string (only present when 'allowed' is "
187 "false)"},
188 {RPCResult::Type::STR, "reject-details", /*optional=*/true,
189 "Rejection details (only present when 'allowed' is false "
190 "and rejection details exist)"},
191
192 }},
193 }},
195 "\nCreate a transaction\n" +
197 "createrawtransaction",
198 "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" "
199 "\"{\\\"myaddress\\\":10000}\"") +
200 "Sign the transaction, and get back the hex\n" +
201 HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
202 "\nTest acceptance of the transaction (signed hex)\n" +
203 HelpExampleCli("testmempoolaccept", R"('["signedhex"]')") +
204 "\nAs a JSON-RPC call\n" +
205 HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]")},
206 [&](const RPCHelpMan &self, const Config &config,
207 const JSONRPCRequest &request) -> UniValue {
208 const UniValue raw_transactions = request.params[0].get_array();
209 if (raw_transactions.size() < 1 ||
210 raw_transactions.size() > MAX_PACKAGE_COUNT) {
212 "Array must contain between 1 and " +
214 " transactions.");
215 }
216
217 const CFeeRate max_raw_tx_fee_rate =
218 request.params[1].isNull()
220 : CFeeRate(AmountFromValue(request.params[1]));
221
222 std::vector<CTransactionRef> txns;
223 txns.reserve(raw_transactions.size());
224 for (const auto &rawtx : raw_transactions.getValues()) {
226 if (!DecodeHexTx(mtx, rawtx.get_str())) {
228 "TX decode failed: " + rawtx.get_str());
229 }
230 txns.emplace_back(MakeTransactionRef(std::move(mtx)));
231 }
232
233 NodeContext &node = EnsureAnyNodeContext(request.context);
234 CTxMemPool &mempool = EnsureMemPool(node);
236 Chainstate &chainstate = chainman.ActiveChainstate();
237 const PackageMempoolAcceptResult package_result = [&] {
239 if (txns.size() > 1) {
240 return ProcessNewPackage(chainstate, mempool, txns,
241 /* test_accept */ true);
242 }
244 txns[0]->GetId(),
245 chainman.ProcessTransaction(txns[0],
246 /* test_accept*/ true));
247 }();
248
249 UniValue rpc_result(UniValue::VARR);
250 // We will check transaction fees while we iterate through txns in
251 // order. If any transaction fee exceeds maxfeerate, we will leave
252 // the rest of the validation results blank, because it doesn't make
253 // sense to return a validation result for a transaction if its
254 // ancestor(s) would not be submitted.
255 bool exit_early{false};
256 for (const auto &tx : txns) {
257 UniValue result_inner(UniValue::VOBJ);
258 result_inner.pushKV("txid", tx->GetId().GetHex());
259 if (package_result.m_state.GetResult() ==
261 result_inner.pushKV(
262 "package-error",
263 package_result.m_state.GetRejectReason());
264 }
265 auto it = package_result.m_tx_results.find(tx->GetId());
266 if (exit_early || it == package_result.m_tx_results.end()) {
267 // Validation unfinished. Just return the txid.
268 rpc_result.push_back(std::move(result_inner));
269 continue;
270 }
271 const auto &tx_result = it->second;
272 // Package testmempoolaccept doesn't allow transactions to
273 // already be in the mempool.
274 CHECK_NONFATAL(tx_result.m_result_type !=
276 if (tx_result.m_result_type ==
278 const Amount fee = tx_result.m_base_fees.value();
279 // Check that fee does not exceed maximum fee
280 const int64_t virtual_size = tx_result.m_vsize.value();
281 const Amount max_raw_tx_fee =
282 max_raw_tx_fee_rate.GetFee(virtual_size);
283 if (max_raw_tx_fee != Amount::zero() &&
284 fee > max_raw_tx_fee) {
285 result_inner.pushKV("allowed", false);
286 result_inner.pushKV("reject-reason",
287 "max-fee-exceeded");
288 exit_early = true;
289 } else {
290 // Only return the fee and size if the transaction
291 // would pass ATMP.
292 // These can be used to calculate the feerate.
293 result_inner.pushKV("allowed", true);
294 result_inner.pushKV("size", virtual_size);
296 fees.pushKV("base", fee);
297 fees.pushKV(
298 "effective-feerate",
299 tx_result.m_effective_feerate.value().GetFeePerK());
300 UniValue effective_includes_res(UniValue::VARR);
301 for (const auto &txid :
302 tx_result.m_txids_fee_calculations.value()) {
303 effective_includes_res.push_back(txid.ToString());
304 }
305 fees.pushKV("effective-includes",
306 std::move(effective_includes_res));
307 result_inner.pushKV("fees", std::move(fees));
308 }
309 } else {
310 result_inner.pushKV("allowed", false);
311 const TxValidationState state = tx_result.m_state;
312 if (state.GetResult() ==
314 result_inner.pushKV("reject-reason", "missing-inputs");
315 } else {
316 result_inner.pushKV("reject-reason",
317 state.GetRejectReason());
318 result_inner.pushKV("reject-details", state.ToString());
319 }
320 }
321 rpc_result.push_back(std::move(result_inner));
322 }
323 return rpc_result;
324 },
325 };
326}
327
328static std::vector<RPCResult> MempoolEntryDescription() {
329 const auto ticker = Currency::getTicker();
330 return {
331 RPCResult{RPCResult::Type::NUM, "size", "transaction size."},
333 "local time transaction entered pool in seconds since 1 Jan "
334 "1970 GMT"},
336 "block height when transaction entered pool"},
338 "fees",
339 "",
340 {{
342 "transaction fee in " + ticker},
344 "transaction fee with fee deltas used for "
345 "mining priority in " +
346 ticker},
347 }}},
348 RPCResult{
350 "depends",
351 "unconfirmed transactions used as inputs for this transaction",
352 {RPCResult{RPCResult::Type::STR_HEX, "transactionid",
353 "parent transaction id"}}},
354 RPCResult{
356 "spentby",
357 "unconfirmed transactions spending outputs from this transaction",
358 {RPCResult{RPCResult::Type::STR_HEX, "transactionid",
359 "child transaction id"}}},
360 RPCResult{RPCResult::Type::BOOL, "unbroadcast",
361 "Whether this transaction is currently unbroadcast (initial "
362 "broadcast not yet acknowledged by any peers)"},
363 };
364}
365
366static void entryToJSON(const CTxMemPool &pool, UniValue &info,
367 const CTxMemPoolEntryRef &e)
368 EXCLUSIVE_LOCKS_REQUIRED(pool.cs) {
369 AssertLockHeld(pool.cs);
370
372 fees.pushKV("base", e->GetFee());
373 fees.pushKV("modified", e->GetModifiedFee());
374 info.pushKV("fees", fees);
375
376 info.pushKV("size", (int)e->GetTxSize());
377 info.pushKV("time", count_seconds(e->GetTime()));
378 info.pushKV("height", (int)e->GetHeight());
379 const CTransaction &tx = e->GetTx();
380 std::set<std::string> setDepends;
381 for (const CTxIn &txin : tx.vin) {
382 if (pool.exists(txin.prevout.GetTxId())) {
383 setDepends.insert(txin.prevout.GetTxId().ToString());
384 }
385 }
386
387 UniValue depends(UniValue::VARR);
388 for (const std::string &dep : setDepends) {
389 depends.push_back(dep);
390 }
391
392 info.pushKV("depends", std::move(depends));
393
395 for (const auto &child : e->GetMemPoolChildrenConst()) {
396 spent.push_back(child.get()->GetTx().GetId().ToString());
397 }
398
399 info.pushKV("spentby", std::move(spent));
400 info.pushKV("unbroadcast", pool.IsUnbroadcastTx(tx.GetId()));
401}
402
403UniValue MempoolToJSON(const CTxMemPool &pool, bool verbose,
404 bool include_mempool_sequence) {
405 if (verbose) {
406 if (include_mempool_sequence) {
407 throw JSONRPCError(
409 "Verbose results cannot contain mempool sequence values.");
410 }
411 LOCK(pool.cs);
413 for (const CTxMemPoolEntryRef &e : pool.mapTx) {
414 const TxId &txid = e->GetTx().GetId();
416 entryToJSON(pool, info, e);
417 // Mempool has unique entries so there is no advantage in using
418 // UniValue::pushKV, which checks if the key already exists in O(N).
419 // UniValue::pushKVEnd is used instead which currently is O(1).
420 o.pushKVEnd(txid.ToString(), std::move(info));
421 }
422 return o;
423 } else {
424 uint64_t mempool_sequence;
425 std::vector<TxId> vtxids;
426 {
427 LOCK(pool.cs);
428 pool.getAllTxIds(vtxids);
429 mempool_sequence = pool.GetSequence();
430 }
432 for (const TxId &txid : vtxids) {
433 a.push_back(txid.ToString());
434 }
435
436 if (!include_mempool_sequence) {
437 return a;
438 } else {
440 o.pushKV("txids", std::move(a));
441 o.pushKV("mempool_sequence", mempool_sequence);
442 return o;
443 }
444 }
445}
446
448 return RPCHelpMan{
449 "getrawmempool",
450 "Returns all transaction ids in memory pool as a json array of "
451 "string transaction ids.\n"
452 "\nHint: use getmempoolentry to fetch a specific transaction from the "
453 "mempool.\n",
454 {
455 {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false},
456 "True for a json object, false for array of transaction ids"},
457 {"mempool_sequence", RPCArg::Type::BOOL, RPCArg::Default{false},
458 "If verbose=false, returns a json object with transaction list "
459 "and mempool sequence number attached."},
460 },
461 {
462 RPCResult{"for verbose = false",
464 "",
465 "",
466 {
467 {RPCResult::Type::STR_HEX, "", "The transaction id"},
468 }},
469 RPCResult{"for verbose = true",
471 "",
472 "",
473 {
474 {RPCResult::Type::OBJ, "transactionid", "",
476 }},
477 RPCResult{
478 "for verbose = false and mempool_sequence = true",
480 "",
481 "",
482 {
484 "txids",
485 "",
486 {
487 {RPCResult::Type::STR_HEX, "", "The transaction id"},
488 }},
489 {RPCResult::Type::NUM, "mempool_sequence",
490 "The mempool sequence value."},
491 }},
492 },
493 RPCExamples{HelpExampleCli("getrawmempool", "true") +
494 HelpExampleRpc("getrawmempool", "true")},
495 [&](const RPCHelpMan &self, const Config &config,
496 const JSONRPCRequest &request) -> UniValue {
497 bool fVerbose = false;
498 if (!request.params[0].isNull()) {
499 fVerbose = request.params[0].get_bool();
500 }
501
502 bool include_mempool_sequence = false;
503 if (!request.params[1].isNull()) {
504 include_mempool_sequence = request.params[1].get_bool();
505 }
506
507 return MempoolToJSON(EnsureAnyMemPool(request.context), fVerbose,
508 include_mempool_sequence);
509 },
510 };
511}
512
514 return RPCHelpMan{
515 "getmempoolancestors",
516 "If txid is in the mempool, returns all in-mempool ancestors.\n",
517 {
519 "The transaction id (must be in mempool)"},
520 {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false},
521 "True for a json object, false for array of transaction ids"},
522 },
523 {
524 RPCResult{
525 "for verbose = false",
527 "",
528 "",
530 "The transaction id of an in-mempool ancestor transaction"}}},
531 RPCResult{"for verbose = true",
533 "",
534 "",
535 {
536 {RPCResult::Type::OBJ, "transactionid", "",
538 }},
539 },
540 RPCExamples{HelpExampleCli("getmempoolancestors", "\"mytxid\"") +
541 HelpExampleRpc("getmempoolancestors", "\"mytxid\"")},
542 [&](const RPCHelpMan &self, const Config &config,
543 const JSONRPCRequest &request) -> UniValue {
544 bool fVerbose = false;
545 if (!request.params[1].isNull()) {
546 fVerbose = request.params[1].get_bool();
547 }
548
549 TxId txid(ParseHashV(request.params[0], "parameter 1"));
550
551 const CTxMemPool &mempool = EnsureAnyMemPool(request.context);
552 LOCK(mempool.cs);
553
554 CTxMemPool::txiter it = mempool.mapTx.find(txid);
555 if (it == mempool.mapTx.end()) {
557 "Transaction not in mempool");
558 }
559
560 CTxMemPool::setEntries setAncestors;
561 mempool.CalculateMemPoolAncestors(*it, setAncestors, false);
562
563 if (!fVerbose) {
565 for (CTxMemPool::txiter ancestorIt : setAncestors) {
566 o.push_back((*ancestorIt)->GetTx().GetId().ToString());
567 }
568 return o;
569 } else {
571 for (CTxMemPool::txiter ancestorIt : setAncestors) {
572 const CTxMemPoolEntryRef &e = *ancestorIt;
573 const TxId &_txid = e->GetTx().GetId();
575 entryToJSON(mempool, info, e);
576 o.pushKV(_txid.ToString(), std::move(info));
577 }
578 return o;
579 }
580 },
581 };
582}
583
585 return RPCHelpMan{
586 "getmempooldescendants",
587 "If txid is in the mempool, returns all in-mempool descendants.\n",
588 {
590 "The transaction id (must be in mempool)"},
591 {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false},
592 "True for a json object, false for array of transaction ids"},
593 },
594 {
595 RPCResult{"for verbose = false",
597 "",
598 "",
600 "The transaction id of an in-mempool descendant "
601 "transaction"}}},
602 RPCResult{"for verbose = true",
604 "",
605 "",
606 {
607 {RPCResult::Type::OBJ, "transactionid", "",
609 }},
610 },
611 RPCExamples{HelpExampleCli("getmempooldescendants", "\"mytxid\"") +
612 HelpExampleRpc("getmempooldescendants", "\"mytxid\"")},
613 [&](const RPCHelpMan &self, const Config &config,
614 const JSONRPCRequest &request) -> UniValue {
615 bool fVerbose = false;
616 if (!request.params[1].isNull()) {
617 fVerbose = request.params[1].get_bool();
618 }
619
620 TxId txid(ParseHashV(request.params[0], "parameter 1"));
621
622 const CTxMemPool &mempool = EnsureAnyMemPool(request.context);
623 LOCK(mempool.cs);
624
625 CTxMemPool::txiter it = mempool.mapTx.find(txid);
626 if (it == mempool.mapTx.end()) {
628 "Transaction not in mempool");
629 }
630
631 CTxMemPool::setEntries setDescendants;
632 mempool.CalculateDescendants(it, setDescendants);
633 // CTxMemPool::CalculateDescendants will include the given tx
634 setDescendants.erase(it);
635
636 if (!fVerbose) {
638 for (CTxMemPool::txiter descendantIt : setDescendants) {
639 o.push_back((*descendantIt)->GetTx().GetId().ToString());
640 }
641
642 return o;
643 } else {
645 for (CTxMemPool::txiter descendantIt : setDescendants) {
646 const CTxMemPoolEntryRef &e = *descendantIt;
647 const TxId &_txid = e->GetTx().GetId();
649 entryToJSON(mempool, info, e);
650 o.pushKV(_txid.ToString(), std::move(info));
651 }
652 return o;
653 }
654 },
655 };
656}
657
659 return RPCHelpMan{
660 "getmempoolentry",
661 "Returns mempool data for given transaction\n",
662 {
664 "The transaction id (must be in mempool)"},
665 },
667 RPCExamples{HelpExampleCli("getmempoolentry", "\"mytxid\"") +
668 HelpExampleRpc("getmempoolentry", "\"mytxid\"")},
669 [&](const RPCHelpMan &self, const Config &config,
670 const JSONRPCRequest &request) -> UniValue {
671 TxId txid(ParseHashV(request.params[0], "parameter 1"));
672
673 const CTxMemPool &mempool = EnsureAnyMemPool(request.context);
674 LOCK(mempool.cs);
675
676 CTxMemPool::txiter it = mempool.mapTx.find(txid);
677 if (it == mempool.mapTx.end()) {
679 "Transaction not in mempool");
680 }
681
683 entryToJSON(mempool, info, *it);
684 return info;
685 },
686 };
687}
688
690 // Make sure this call is atomic in the pool.
691 LOCK(pool.cs);
693 ret.pushKV("loaded", pool.GetLoadTried());
694 ret.pushKV("size", (int64_t)pool.size());
695 ret.pushKV("bytes", (int64_t)pool.GetTotalTxSize());
696 ret.pushKV("finalized_txs_size", (int64_t)pool.GetFinalizedTxCount());
697 ret.pushKV("finalized_txs_bytes", (int64_t)pool.GetTotalFinalizedTxSize());
698 ret.pushKV("finalized_txs_sigchecks",
699 (int64_t)pool.GetTotalFinalizedTxSigchecks());
700 ret.pushKV("usage", (int64_t)pool.DynamicMemoryUsage());
701 ret.pushKV("total_fee", pool.GetTotalFee());
702 ret.pushKV("maxmempool", pool.m_opts.max_size_bytes);
703 ret.pushKV(
704 "mempoolminfee",
705 std::max(pool.GetMinFee(), pool.m_opts.min_relay_feerate).GetFeePerK());
706 ret.pushKV("minrelaytxfee", pool.m_opts.min_relay_feerate.GetFeePerK());
707 ret.pushKV("unbroadcastcount", uint64_t{pool.GetUnbroadcastTxs().size()});
708 return ret;
709}
710
712 const auto ticker = Currency::getTicker();
713 return RPCHelpMan{
714 "getmempoolinfo",
715 "Returns details on the active state of the TX memory pool.\n",
716 {},
717 RPCResult{
719 "",
720 "",
721 {
722 {RPCResult::Type::BOOL, "loaded",
723 "True if the initial load attempt of the persisted mempool "
724 "finished"},
725 {RPCResult::Type::NUM, "size", "Current tx count"},
726 {RPCResult::Type::NUM, "bytes", "Sum of all transaction sizes"},
727 {RPCResult::Type::NUM, "finalized_txs_size",
728 "Current finalized tx count"},
729 {RPCResult::Type::NUM, "finalized_txs_bytes",
730 "Sum of all finalized transaction sizes"},
731 {RPCResult::Type::NUM, "finalized_txs_sigchecks",
732 "Sum of all finalized transaction sigchecks"},
733 {RPCResult::Type::NUM, "usage",
734 "Total memory usage for the mempool"},
735 {RPCResult::Type::NUM, "maxmempool",
736 "Maximum memory usage for the mempool"},
737 {RPCResult::Type::STR_AMOUNT, "total_fee",
738 "Total fees for the mempool in " + ticker +
739 ", ignoring modified fees through prioritizetransaction"},
740 {RPCResult::Type::STR_AMOUNT, "mempoolminfee",
741 "Minimum fee rate in " + ticker +
742 "/kB for tx to be accepted. Is the maximum of "
743 "minrelaytxfee and minimum mempool fee"},
744 {RPCResult::Type::STR_AMOUNT, "minrelaytxfee",
745 "Current minimum relay fee for transactions"},
746 {RPCResult::Type::NUM, "unbroadcastcount",
747 "Current number of transactions that haven't passed initial "
748 "broadcast yet"},
749 }},
750 RPCExamples{HelpExampleCli("getmempoolinfo", "") +
751 HelpExampleRpc("getmempoolinfo", "")},
752 [&](const RPCHelpMan &self, const Config &config,
753 const JSONRPCRequest &request) -> UniValue {
754 return MempoolInfoToJSON(EnsureAnyMemPool(request.context));
755 },
756 };
757}
758
760 return RPCHelpMan{
761 "importmempool",
762 "Import a mempool.dat file and attempt to add its contents to the "
763 "mempool.\n"
764 "Warning: Importing untrusted files is dangerous, especially if "
765 "metadata from the file is taken over.",
766 {
768 "The mempool file"},
769 {"options",
772 "",
773 {
774 {"use_current_time", RPCArg::Type::BOOL, RPCArg::Default{true},
775 "Whether to use the current system time or use the entry "
776 "time metadata from the mempool file.\n"
777 "Warning: Importing untrusted metadata may lead to "
778 "unexpected issues and undesirable behavior."},
779 {"apply_fee_delta_priority", RPCArg::Type::BOOL,
780 RPCArg::Default{false},
781 "Whether to apply the fee delta metadata from the mempool "
782 "file.\n"
783 "It will be added to any existing fee deltas.\n"
784 "The fee delta can be set by the prioritisetransaction RPC.\n"
785 "Warning: Importing untrusted metadata may lead to "
786 "unexpected issues and undesirable behavior.\n"
787 "Only set this bool if you understand what it does."},
788 {"apply_unbroadcast_set", RPCArg::Type::BOOL,
789 RPCArg::Default{false},
790 "Whether to apply the unbroadcast set metadata from the "
791 "mempool file.\n"
792 "Warning: Importing untrusted metadata may lead to "
793 "unexpected issues and undesirable behavior."},
794 },
795 RPCArgOptions{.oneline_description = "\"options\""}},
796 },
797 RPCResult{RPCResult::Type::OBJ, "", "", std::vector<RPCResult>{}},
798 RPCExamples{HelpExampleCli("importmempool", "/path/to/mempool.dat") +
799 HelpExampleRpc("importmempool", "/path/to/mempool.dat")},
800 [&](const RPCHelpMan &self, const Config &config,
801 const JSONRPCRequest &request) -> UniValue {
802 const NodeContext &node{EnsureAnyNodeContext(request.context)};
803
804 CTxMemPool &mempool{EnsureMemPool(node)};
806 Chainstate &chainstate = chainman.ActiveChainstate();
807
808 if (chainman.IsInitialBlockDownload()) {
810 "Can only import the mempool after the "
811 "block download and sync is done.");
812 }
813
814 const fs::path load_path{fs::u8path(request.params[0].get_str())};
815 const UniValue &use_current_time{
816 request.params[1]["use_current_time"]};
817 const UniValue &apply_fee_delta{
818 request.params[1]["apply_fee_delta_priority"]};
819 const UniValue &apply_unbroadcast{
820 request.params[1]["apply_unbroadcast_set"]};
822 .use_current_time = use_current_time.isNull()
823 ? true
824 : use_current_time.get_bool(),
825 .apply_fee_delta_priority = apply_fee_delta.isNull()
826 ? false
827 : apply_fee_delta.get_bool(),
828 .apply_unbroadcast_set = apply_unbroadcast.isNull()
829 ? false
830 : apply_unbroadcast.get_bool(),
831 };
832
833 if (!kernel::LoadMempool(mempool, load_path, chainstate,
834 std::move(opts))) {
836 "Unable to import mempool file, see "
837 "debug.log for details.");
838 }
839
841 return ret;
842 },
843 };
844}
845
847 return RPCHelpMan{
848 "savemempool",
849 "Dumps the mempool to disk. It will fail until the previous dump is "
850 "fully loaded.\n",
851 {},
853 "",
854 "",
855 {
856 {RPCResult::Type::STR, "filename",
857 "the directory and file where the mempool was saved"},
858 }},
859 RPCExamples{HelpExampleCli("savemempool", "") +
860 HelpExampleRpc("savemempool", "")},
861 [&](const RPCHelpMan &self, const Config &config,
862 const JSONRPCRequest &request) -> UniValue {
863 const ArgsManager &args{EnsureAnyArgsman(request.context)};
864 const CTxMemPool &mempool = EnsureAnyMemPool(request.context);
865
866 if (!mempool.GetLoadTried()) {
868 "The mempool was not loaded yet");
869 }
870
871 const fs::path &dump_path = MempoolPath(args);
872
873 if (!DumpMempool(mempool, dump_path)) {
875 "Unable to dump mempool to disk");
876 }
877
879 ret.pushKV("filename", dump_path.u8string());
880
881 return ret;
882 },
883 };
884}
885
887 const auto ticker = Currency::getTicker();
888 return RPCHelpMan{
889 "submitpackage",
890 "Submit a package of raw transactions (serialized, hex-encoded) to "
891 "local node.\n"
892 "The package must consist of a child with its parents, and none of the "
893 "parents may depend on one another.\n"
894 "The package will be validated according to consensus and mempool "
895 "policy rules. If any transaction passes, it will be accepted to "
896 "mempool.\n"
897 "This RPC is experimental and the interface may be unstable. Refer to "
898 "doc/policy/packages.md for documentation on package policies.\n"
899 "Warning: successful submission does not mean the transactions will "
900 "propagate throughout the network.\n",
901 {
902 {
903 "package",
906 "An array of raw transactions.",
907 {
909 ""},
910 },
911 },
912 },
913 RPCResult{
915 "",
916 "",
917 {
918 {RPCResult::Type::STR, "package_msg",
919 "The transaction package result message. \"success\" "
920 "indicates all transactions were accepted into or are already "
921 "in the mempool."},
923 "tx-results",
924 "transaction results keyed by txid",
926 "txid",
927 "transaction txid",
928 {
929 {RPCResult::Type::NUM, "vsize", /*optional=*/true,
930 "Virtual transaction size."},
932 "fees",
933 /*optional=*/true,
934 "Transaction fees",
935 {
937 "transaction fee in " + ticker},
938 {RPCResult::Type::STR_AMOUNT, "effective-feerate",
939 "the effective feerate in " + ticker +
940 " per KvB. May differ from the base feerate "
941 "if, for example, there are modified fees "
942 "from prioritisetransaction or a package "
943 "feerate was used."},
945 "effective-includes",
946 "transactions whose fees and vsizes are included "
947 "in effective-feerate.",
948 {
950 "transaction txid in hex"},
951 }},
952 }},
953 {RPCResult::Type::STR, "error", /*optional=*/true,
954 "The transaction error string, if it was rejected by "
955 "the mempool"},
956 }}}},
957 },
958 },
959 RPCExamples{HelpExampleCli("testmempoolaccept", "[rawtx1, rawtx2]") +
960 HelpExampleCli("submitpackage", "[rawtx1, rawtx2]")},
961 [&](const RPCHelpMan &self, const Config &config,
962 const JSONRPCRequest &request) -> UniValue {
963 const UniValue &raw_transactions = request.params[0].get_array();
964 if (raw_transactions.size() < 1 ||
965 raw_transactions.size() > MAX_PACKAGE_COUNT) {
967 "Array must contain between 1 and " +
969 " transactions.");
970 }
971
972 std::vector<CTransactionRef> txns;
973 txns.reserve(raw_transactions.size());
974 for (const auto &rawtx : raw_transactions.getValues()) {
976 if (!DecodeHexTx(mtx, rawtx.get_str())) {
977 throw JSONRPCError(
979 "TX decode failed: " + rawtx.get_str() +
980 " Make sure the tx has at least one input.");
981 }
982 txns.emplace_back(MakeTransactionRef(std::move(mtx)));
983 }
984 if (!IsChildWithParentsTree(txns)) {
986 TransactionError::INVALID_PACKAGE,
987 "package topology disallowed. not child-with-parents or "
988 "parents depend on each other.");
989 }
990
991 NodeContext &node = EnsureAnyNodeContext(request.context);
992 CTxMemPool &mempool = EnsureMemPool(node);
994 const auto package_result = WITH_LOCK(
995 ::cs_main, return ProcessNewPackage(chainstate, mempool, txns,
996 /*test_accept=*/false));
997
998 std::string package_msg = "success";
999
1000 // First catch package-wide errors, continue if we can
1001 switch (package_result.m_state.GetResult()) {
1003 // Belt-and-suspenders check; everything should be
1004 // successful here
1005 CHECK_NONFATAL(package_result.m_tx_results.size() ==
1006 txns.size());
1007 for (const auto &tx : txns) {
1008 CHECK_NONFATAL(mempool.exists(tx->GetId()));
1009 }
1010 break;
1011 }
1013 // This only happens with internal bug; user should stop and
1014 // report
1016 TransactionError::MEMPOOL_ERROR,
1017 package_result.m_state.GetRejectReason());
1018 }
1021 // Package-wide error we want to return, but we also want to
1022 // return individual responses
1023 package_msg = package_result.m_state.GetRejectReason();
1024 CHECK_NONFATAL(package_result.m_tx_results.size() ==
1025 txns.size() ||
1026 package_result.m_tx_results.empty());
1027 break;
1028 }
1029 }
1030 size_t num_broadcast{0};
1031 for (const auto &tx : txns) {
1032 // We don't want to re-submit the txn for validation in
1033 // BroadcastTransaction
1034 if (!mempool.exists(tx->GetId())) {
1035 continue;
1036 }
1037
1038 // We do not expect an error here; we are only broadcasting
1039 // things already/still in mempool
1040 std::string err_string;
1041 const auto err = BroadcastTransaction(
1042 node, tx, err_string, /*max_tx_fee=*/Amount::zero(),
1043 /*relay=*/true, /*wait_callback=*/true);
1044 if (err != TransactionError::OK) {
1046 err,
1047 strprintf("transaction broadcast failed: %s (%d "
1048 "transactions were broadcast successfully)",
1049 err_string, num_broadcast));
1050 }
1051 num_broadcast++;
1052 }
1053
1054 UniValue rpc_result{UniValue::VOBJ};
1055 rpc_result.pushKV("package_msg", package_msg);
1056 UniValue tx_result_map{UniValue::VOBJ};
1057 for (const auto &tx : txns) {
1058 UniValue result_inner{UniValue::VOBJ};
1059 auto it = package_result.m_tx_results.find(tx->GetId());
1060 if (it == package_result.m_tx_results.end()) {
1061 // No results, report error and continue
1062 result_inner.pushKV("error", "unevaluated");
1063 continue;
1064 }
1065 const auto &tx_result = it->second;
1066 switch (it->second.m_result_type) {
1068 result_inner.pushKV("error",
1069 it->second.m_state.ToString());
1070 break;
1073 result_inner.pushKV(
1074 "vsize", int64_t{it->second.m_vsize.value()});
1076 fees.pushKV("base", it->second.m_base_fees.value());
1077 if (tx_result.m_result_type ==
1079 // Effective feerate is not provided for
1080 // MEMPOOL_ENTRY (already in mempool) transactions
1081 // even though modified fees is known, because it is
1082 // unknown whether package feerate was used when it
1083 // was originally submitted.
1084 fees.pushKV("effective-feerate",
1085 tx_result.m_effective_feerate.value()
1086 .GetFeePerK());
1087 UniValue effective_includes_res(UniValue::VARR);
1088 for (const auto &txid :
1089 tx_result.m_txids_fee_calculations.value()) {
1090 effective_includes_res.push_back(
1091 txid.ToString());
1092 }
1093 fees.pushKV("effective-includes",
1094 std::move(effective_includes_res));
1095 }
1096 result_inner.pushKV("fees", std::move(fees));
1097 break;
1098 }
1099 tx_result_map.pushKV(tx->GetId().GetHex(),
1100 std::move(result_inner));
1101 }
1102 rpc_result.pushKV("tx-results", std::move(tx_result_map));
1103
1104 return rpc_result;
1105 },
1106 };
1107}
1108
1110 static const CRPCCommand commands[]{
1111 // category actor (function)
1112 // -------- ----------------
1113 {"rawtransactions", sendrawtransaction},
1114 {"rawtransactions", testmempoolaccept},
1115 {"blockchain", getmempoolancestors},
1116 {"blockchain", getmempooldescendants},
1117 {"blockchain", getmempoolentry},
1118 {"blockchain", getmempoolinfo},
1119 {"blockchain", getrawmempool},
1120 {"blockchain", importmempool},
1121 {"blockchain", savemempool},
1122 {"rawtransactions", submitpackage},
1123 };
1124 for (const auto &c : commands) {
1125 t.appendCommand(c.name, &c);
1126 }
1127}
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:83
Fee rate in satoshis per kilobyte: Amount / kB.
Definition: feerate.h:21
Amount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
Definition: feerate.h:54
Amount GetFee(size_t nBytes) const
Return the fee in satoshis for the given size in bytes.
Definition: feerate.cpp:49
A mutable version of CTransaction.
Definition: transaction.h:274
RPC command dispatcher.
Definition: server.h:194
void appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
Definition: server.cpp:330
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:222
std::set< txiter, CompareIteratorById > setEntries
Definition: txmempool.h:320
bool GetLoadTried() const
Definition: txmempool.cpp:1021
CFeeRate GetMinFee() const
The minimum fee to get into the mempool, which may itself not be enough for larger-sized transactions...
Definition: txmempool.h:456
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
Definition: txmempool.h:316
Amount GetTotalFee() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.h:523
uint64_t GetTotalFinalizedTxSigchecks() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.h:514
void getAllTxIds(std::vector< TxId > &vtxid) const
Definition: txmempool.cpp:515
size_t DynamicMemoryUsage() const
Definition: txmempool.cpp:814
const Options m_opts
Definition: txmempool.h:353
bool exists(const TxId &txid) const
Definition: txmempool.h:528
std::set< TxId > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
Definition: txmempool.h:567
uint64_t GetSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.h:583
indexed_transaction_set::nth_index< 0 >::type::const_iterator txiter
Definition: txmempool.h:319
uint64_t GetFinalizedTxCount() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.h:503
bool CalculateMemPoolAncestors(const CTxMemPoolEntryRef &entry, setEntries &setAncestors, bool fSearchForParents=true) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Try to calculate all in-mempool ancestors of entry.
Definition: txmempool.cpp:58
uint64_t GetTotalFinalizedTxSize() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.h:508
void CalculateDescendants(txiter it, setEntries &setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Populate setDescendants with all in-mempool descendants of hash.
Definition: txmempool.cpp:241
unsigned long size() const
Definition: txmempool.h:493
uint64_t GetTotalTxSize() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.h:498
Chainstate stores and provides an API to update our local knowledge of the current best chain.
Definition: validation.h:725
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
Definition: validation.h:1174
SnapshotCompletionResult MaybeCompleteSnapshotValidation() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex *GetSnapshotBaseBlock() const EXCLUSIVE_LOCKS_REQUIRED(Chainstate ActiveChainstate)() const
Once the background validation chainstate has reached the height which is the base of the UTXO snapsh...
Definition: validation.h:1428
MempoolAcceptResult ProcessTransaction(const CTransactionRef &tx, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Try to add a transaction to the memory pool.
bool IsInitialBlockDownload() const
Check whether we are doing an initial block download (synchronizing from disk or network)
Definition: config.h:19
Definition: rcu.h:85
void push_back(UniValue val)
Definition: univalue.cpp:96
@ VOBJ
Definition: univalue.h:31
@ VARR
Definition: univalue.h:32
size_t size() const
Definition: univalue.h:92
const std::vector< UniValue > & getValues() const
void pushKVEnd(std::string key, UniValue val)
Definition: univalue.cpp:108
const UniValue & get_array() const
void pushKV(std::string key, UniValue val)
Definition: univalue.cpp:115
bool get_bool() const
std::string GetRejectReason() const
Definition: validation.h:123
Result GetResult() const
Definition: validation.h:122
std::string ToString() const
Definition: validation.h:125
std::string ToString() const
Definition: uint256.h:80
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:30
std::string u8string() const
Definition: fs.h:72
@ TX_MISSING_INPUTS
transaction was missing some of its inputs
bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx)
Definition: core_read.cpp:196
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: cs_main.cpp:7
static RPCHelpMan getmempoolinfo()
Definition: mempool.cpp:711
static RPCHelpMan sendrawtransaction()
Definition: mempool.cpp:34
static RPCHelpMan importmempool()
Definition: mempool.cpp:759
void RegisterMempoolRPCCommands(CRPCTable &t)
Register mempool RPC commands.
Definition: mempool.cpp:1109
static RPCHelpMan getrawmempool()
Definition: mempool.cpp:447
static RPCHelpMan getmempoolentry()
Definition: mempool.cpp:658
UniValue MempoolInfoToJSON(const CTxMemPool &pool)
Mempool information to JSON.
Definition: mempool.cpp:689
static std::vector< RPCResult > MempoolEntryDescription()
Definition: mempool.cpp:328
static RPCHelpMan submitpackage()
Definition: mempool.cpp:886
UniValue MempoolToJSON(const CTxMemPool &pool, bool verbose, bool include_mempool_sequence)
Mempool to JSON.
Definition: mempool.cpp:403
static void entryToJSON(const CTxMemPool &pool, UniValue &info, const CTxMemPoolEntryRef &e) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
Definition: mempool.cpp:366
static RPCHelpMan testmempoolaccept()
Definition: mempool.cpp:103
static RPCHelpMan getmempooldescendants()
Definition: mempool.cpp:584
static RPCHelpMan getmempoolancestors()
Definition: mempool.cpp:513
static RPCHelpMan savemempool()
Definition: mempool.cpp:846
std::string FormatMoney(const Amount amt)
Do not use these functions to represent or parse monetary amounts to or from JSON but use AmountFromV...
Definition: moneystr.cpp:13
static path u8path(const std::string &utf8_str)
Definition: fs.h:90
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.
bool DumpMempool(const CTxMemPool &pool, const fs::path &dump_path, FopenFn mockable_fopen_function, bool skip_file_commit)
Definition: messages.h:12
TransactionError BroadcastTransaction(const NodeContext &node, const CTransactionRef tx, std::string &err_string, const Amount max_tx_fee, bool relay, bool wait_callback)
Submit a transaction to the mempool and (optionally) relay it to all P2P peers.
Definition: transaction.cpp:38
TransactionError
Definition: types.h:17
fs::path MempoolPath(const ArgsManager &argsman)
static const CFeeRate DEFAULT_MAX_RAW_TX_FEE_RATE
Maximum fee rate for sendrawtransaction and testmempoolaccept RPC calls.
Definition: transaction.h:33
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:150
is a home for public enum and struct type definitions that are used by internally by node code,...
bool IsChildWithParentsTree(const Package &package)
Context-free check that a package IsChildWithParents() and none of the parents depend on each other (...
Definition: packages.cpp:109
static constexpr uint32_t MAX_PACKAGE_COUNT
Default maximum number of transactions in a package.
Definition: packages.h:15
@ PCKG_POLICY
The package itself is invalid (e.g. too many transactions).
@ PCKG_RESULT_UNSET
Initial value. The package has not yet been rejected.
@ PCKG_MEMPOOL_ERROR
Mempool logic error.
@ PCKG_TX
At least one tx is invalid.
int64_t GetVirtualTransactionSize(int64_t nSize, int64_t nSigChecks, unsigned int bytes_per_sigCheck)
Compute the virtual transaction size (size, or more if sigChecks are too dense).
Definition: policy.cpp:165
static CTransactionRef MakeTransactionRef()
Definition: transaction.h:316
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:315
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:58
@ RPC_MISC_ERROR
General application defined errors std::exception thrown in command handling.
Definition: protocol.h:38
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition: protocol.h:46
@ RPC_CLIENT_IN_INITIAL_DOWNLOAD
Still downloading initial blocks.
Definition: protocol.h:71
@ RPC_DESERIALIZATION_ERROR
Error parsing or validating structure in raw format.
Definition: protocol.h:50
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
Definition: protocol.h:42
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:163
UniValue JSONRPCTransactionError(TransactionError terr, const std::string &err_string)
Definition: util.cpp:356
Amount AmountFromValue(const UniValue &value)
Definition: util.cpp:68
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:180
uint256 ParseHashV(const UniValue &v, std::string strName)
Utilities: convert hex-encoded values (throws error if not hex).
Definition: util.cpp:86
static std::string ToString(const CService &ip)
Definition: db.h:36
NodeContext & EnsureAnyNodeContext(const std::any &context)
Definition: server_util.cpp:21
CTxMemPool & EnsureMemPool(const NodeContext &node)
Definition: server_util.cpp:29
ChainstateManager & EnsureChainman(const NodeContext &node)
Definition: server_util.cpp:52
CTxMemPool & EnsureAnyMemPool(const std::any &context)
Definition: server_util.cpp:37
ArgsManager & EnsureAnyArgsman(const std::any &context)
Definition: server_util.cpp:48
Definition: amount.h:23
static constexpr Amount zero() noexcept
Definition: amount.h:36
static std::string getTicker()
Definition: amount.h:163
@ MEMPOOL_ENTRY
Valid, transaction was already in the mempool.
@ VALID
Fully validated, valid.
Validation result for package mempool acceptance.
Definition: validation.h:297
PackageValidationState m_state
Definition: validation.h:298
std::map< TxId, MempoolAcceptResult > m_tx_results
Map from txid to finished MempoolAcceptResults.
Definition: validation.h:306
@ STR_HEX
Special type that is a STR with only hex chars.
@ AMOUNT
Special type representing a floating point amount (can be either NUM or STR)
@ OBJ_NAMED_PARAMS
Special type that behaves almost exactly like OBJ, defining an options object with a list of pre-defi...
@ OMITTED
Optional argument for which the default value is omitted from help text for one of two reasons:
@ NO
Required arg.
std::string oneline_description
Should be empty unless it is supposed to override the auto-generated summary line.
Definition: util.h:149
@ NUM_TIME
Special numeric to denote unix epoch time.
@ OBJ_DYN
Special dictionary with keys that are not literals.
@ STR_HEX
Special string with only hex chars.
@ STR_AMOUNT
Special string to represent a floating point amount.
A TxId is the identifier of a transaction.
Definition: txid.h:14
CFeeRate min_relay_feerate
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation)
NodeContext struct containing references to chain state and connection state.
Definition: context.h:49
#define AssertLockNotHeld(cs)
Definition: sync.h:163
#define LOCK(cs)
Definition: sync.h:306
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:357
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:56
constexpr int64_t count_seconds(std::chrono::seconds t)
Definition: time.h:85
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202
PackageMempoolAcceptResult ProcessNewPackage(Chainstate &active_chainstate, CTxMemPool &pool, const Package &package, bool test_accept)
Validate (and maybe submit) a package to the mempool.
AssertLockHeld(pool.cs)