Coverage Report

Created: 2026-07-23 20:35

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