mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-05-13 03:30:42 +02:00
Merge 29016 via rpc_listmempooltxs-28+knots
This commit is contained in:
commit
8bc551ae42
@ -268,6 +268,7 @@ BITCOIN_CORE_H = \
|
|||||||
rpc/mempool.h \
|
rpc/mempool.h \
|
||||||
rpc/mining.h \
|
rpc/mining.h \
|
||||||
rpc/protocol.h \
|
rpc/protocol.h \
|
||||||
|
rpc/rawtransaction.h \
|
||||||
rpc/rawtransaction_util.h \
|
rpc/rawtransaction_util.h \
|
||||||
rpc/register.h \
|
rpc/register.h \
|
||||||
rpc/request.h \
|
rpc/request.h \
|
||||||
|
40
src/rest.cpp
40
src/rest.cpp
@ -644,6 +644,45 @@ static bool rest_deploymentinfo(const std::any& context, HTTPRequest* req, const
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool rest_mempool_transactions(const std::any& context, HTTPRequest* req, const std::string& str_uri_part)
|
||||||
|
{
|
||||||
|
if (!CheckWarmup(req))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::string param;
|
||||||
|
const RESTResponseFormat rf = ParseDataFormat(param, str_uri_part);
|
||||||
|
if (param != "contents" && param != "info") {
|
||||||
|
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid URI format. Expected /rest/mempool/transactions/<info|contents>.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
const CTxMemPool* mempool = GetMemPool(context, req);
|
||||||
|
if (!mempool) return false;
|
||||||
|
|
||||||
|
switch (rf) {
|
||||||
|
case RESTResponseFormat::JSON: {
|
||||||
|
std::string str_json;
|
||||||
|
std::string raw_sequence_start;
|
||||||
|
const bool verbose = param == "contents";
|
||||||
|
|
||||||
|
try {
|
||||||
|
raw_sequence_start = req->GetQueryParameter("sequence_start").value_or("0");
|
||||||
|
} catch (const std::runtime_error& e) {
|
||||||
|
return RESTERR(req, HTTP_BAD_REQUEST, e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto sequence_start{ToIntegral<uint64_t>(raw_sequence_start)};
|
||||||
|
str_json = MempoolTxsToJSON(*mempool, verbose, sequence_start.value()).write() + "\n";
|
||||||
|
|
||||||
|
req->WriteHeader("Content-Type", "application/json");
|
||||||
|
req->WriteReply(HTTP_OK, str_json);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: json)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool rest_mempool(const std::any& context, HTTPRequest* req, const std::string& str_uri_part)
|
static bool rest_mempool(const std::any& context, HTTPRequest* req, const std::string& str_uri_part)
|
||||||
{
|
{
|
||||||
if (!CheckWarmup(req))
|
if (!CheckWarmup(req))
|
||||||
@ -1017,6 +1056,7 @@ static const struct {
|
|||||||
{"/rest/blockfilterheaders/", rest_filter_header},
|
{"/rest/blockfilterheaders/", rest_filter_header},
|
||||||
{"/rest/chaininfo", rest_chaininfo},
|
{"/rest/chaininfo", rest_chaininfo},
|
||||||
{"/rest/mempool/", rest_mempool},
|
{"/rest/mempool/", rest_mempool},
|
||||||
|
{"/rest/mempool/transactions", rest_mempool_transactions},
|
||||||
{"/rest/headers/", rest_headers},
|
{"/rest/headers/", rest_headers},
|
||||||
{"/rest/getutxos", rest_getutxos},
|
{"/rest/getutxos", rest_getutxos},
|
||||||
{"/rest/deploymentinfo/", rest_deploymentinfo},
|
{"/rest/deploymentinfo/", rest_deploymentinfo},
|
||||||
|
@ -333,6 +333,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||||||
{ "stop", 0, "wait" },
|
{ "stop", 0, "wait" },
|
||||||
{ "addnode", 2, "v2transport" },
|
{ "addnode", 2, "v2transport" },
|
||||||
{ "addconnection", 2, "v2transport" },
|
{ "addconnection", 2, "v2transport" },
|
||||||
|
{ "listmempooltransactions", 0, "start_sequence"},
|
||||||
|
{ "listmempooltransactions", 1, "verbose"},
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
#include <policy/settings.h>
|
#include <policy/settings.h>
|
||||||
#include <primitives/transaction.h>
|
#include <primitives/transaction.h>
|
||||||
#include <rpc/mempool.h>
|
#include <rpc/mempool.h>
|
||||||
|
#include <rpc/rawtransaction.h>
|
||||||
|
#include <rpc/mempool.h>
|
||||||
#include <rpc/server.h>
|
#include <rpc/server.h>
|
||||||
#include <rpc/server_util.h>
|
#include <rpc/server_util.h>
|
||||||
#include <rpc/util.h>
|
#include <rpc/util.h>
|
||||||
@ -412,6 +414,100 @@ static RPCHelpMan maxmempool()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static RPCHelpMan listmempooltransactions()
|
||||||
|
{
|
||||||
|
return RPCHelpMan{"listmempooltransactions",
|
||||||
|
"\nReturns all transactions in the mempool. Can be filtered by mempool_sequence\n"
|
||||||
|
"\nAllows for syncing with current mempool entries via polling (not zmq).",
|
||||||
|
{
|
||||||
|
{"start_sequence", RPCArg::Type::NUM, RPCArg::Default{0}, "The mempool_sequence to start the results to. Defaults to 0 (zero, all transactions)."},
|
||||||
|
{"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "True for a json object, false for array of transaction ids"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
RPCResult{"for verbose = false",
|
||||||
|
RPCResult::Type::OBJ, "", "",
|
||||||
|
{
|
||||||
|
{RPCResult::Type::NUM, "mempool_sequence", "The current max mempool sequence value."},
|
||||||
|
{RPCResult::Type::ARR, "txs", "",
|
||||||
|
{
|
||||||
|
{RPCResult::Type::OBJ, "", "",
|
||||||
|
{
|
||||||
|
{RPCResult::Type::NUM, "entry_sequence", "The mempool sequence value for this transaction entry."},
|
||||||
|
{RPCResult::Type::STR_HEX, "txid", "The transaction id"},
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
RPCResult{"for verbose = true",
|
||||||
|
RPCResult::Type::OBJ, "", "",
|
||||||
|
{
|
||||||
|
{RPCResult::Type::NUM, "mempool_sequence", "The current max mempool sequence value."},
|
||||||
|
{RPCResult::Type::ARR, "txs", "",
|
||||||
|
{
|
||||||
|
{RPCResult::Type::OBJ, "", "",
|
||||||
|
{
|
||||||
|
Cat<std::vector<RPCResult>>(
|
||||||
|
{
|
||||||
|
{RPCResult::Type::NUM, "entry_sequence", "The mempool sequence value for this transaction entry."},
|
||||||
|
},
|
||||||
|
DecodeTxDoc(/*txid_field_doc=*/"The transaction id of the mempool transaction")),
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
RPCExamples{
|
||||||
|
HelpExampleCli("listmempooltransactions", "true")
|
||||||
|
+ HelpExampleRpc("listmempooltransactions", "true")
|
||||||
|
},
|
||||||
|
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||||
|
{
|
||||||
|
uint64_t start_mempool_sequence = 0;
|
||||||
|
if (!request.params[0].isNull()) {
|
||||||
|
start_mempool_sequence = request.params[0].getInt<uint64_t>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fVerbose = false;
|
||||||
|
if (!request.params[1].isNull())
|
||||||
|
fVerbose = request.params[1].get_bool();
|
||||||
|
|
||||||
|
return MempoolTxsToJSON(EnsureAnyMemPool(request.context), fVerbose, start_mempool_sequence);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
UniValue MempoolTxsToJSON(const CTxMemPool& pool, bool verbose, uint64_t sequence_start)
|
||||||
|
{
|
||||||
|
uint64_t mempool_sequence;
|
||||||
|
|
||||||
|
LOCK(pool.cs);
|
||||||
|
mempool_sequence = pool.GetSequence();
|
||||||
|
|
||||||
|
UniValue o(UniValue::VOBJ);
|
||||||
|
o.pushKV("mempool_sequence", mempool_sequence);
|
||||||
|
|
||||||
|
UniValue a(UniValue::VARR);
|
||||||
|
for (const CTxMemPoolEntry& e : pool.mapTx) {
|
||||||
|
UniValue txentry(UniValue::VOBJ);
|
||||||
|
|
||||||
|
// We skip anything not requested.
|
||||||
|
if (e.GetSequence() < sequence_start)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
txentry.pushKV("entry_sequence", e.GetSequence());
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
// We could also calculate fees etc for this transaction, but yolo.
|
||||||
|
TxToUniv(e.GetTx(), /*block_hash=*/uint256::ZERO, /*entry=*/txentry, /*include_hex=*/false);
|
||||||
|
} else {
|
||||||
|
txentry.pushKV("txid", e.GetTx().GetHash().ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
a.push_back(txentry);
|
||||||
|
}
|
||||||
|
|
||||||
|
o.pushKV("txs", a);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
static RPCHelpMan getrawmempool()
|
static RPCHelpMan getrawmempool()
|
||||||
{
|
{
|
||||||
return RPCHelpMan{"getrawmempool",
|
return RPCHelpMan{"getrawmempool",
|
||||||
@ -1171,6 +1267,7 @@ void RegisterMempoolRPCCommands(CRPCTable& t)
|
|||||||
{"blockchain", &savemempool},
|
{"blockchain", &savemempool},
|
||||||
{"blockchain", &maxmempool},
|
{"blockchain", &maxmempool},
|
||||||
{"rawtransactions", &submitpackage},
|
{"rawtransactions", &submitpackage},
|
||||||
|
{"rawtransactions", &listmempooltransactions},
|
||||||
};
|
};
|
||||||
for (const auto& c : commands) {
|
for (const auto& c : commands) {
|
||||||
t.appendCommand(c.name, &c);
|
t.appendCommand(c.name, &c);
|
||||||
|
@ -30,4 +30,7 @@ UniValue MempoolInfoToJSON(const CTxMemPool& pool, const std::optional<MempoolHi
|
|||||||
/** Mempool to JSON */
|
/** Mempool to JSON */
|
||||||
UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose = false, bool include_mempool_sequence = false);
|
UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose = false, bool include_mempool_sequence = false);
|
||||||
|
|
||||||
|
/** Mempool Txs to JSON */
|
||||||
|
UniValue MempoolTxsToJSON(const CTxMemPool& pool, bool verbose = false, uint64_t sequence_start = 0);
|
||||||
|
|
||||||
#endif // BITCOIN_RPC_MEMPOOL_H
|
#endif // BITCOIN_RPC_MEMPOOL_H
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <psbt.h>
|
#include <psbt.h>
|
||||||
#include <random.h>
|
#include <random.h>
|
||||||
#include <rpc/blockchain.h>
|
#include <rpc/blockchain.h>
|
||||||
|
#include <rpc/rawtransaction.h>
|
||||||
#include <rpc/rawtransaction_util.h>
|
#include <rpc/rawtransaction_util.h>
|
||||||
#include <rpc/server.h>
|
#include <rpc/server.h>
|
||||||
#include <rpc/server_util.h>
|
#include <rpc/server_util.h>
|
||||||
@ -99,7 +100,7 @@ static std::vector<RPCResult> ScriptPubKeyDoc() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<RPCResult> DecodeTxDoc(const std::string& txid_field_doc)
|
std::vector<RPCResult> DecodeTxDoc(const std::string& txid_field_doc)
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
{RPCResult::Type::STR_HEX, "txid", txid_field_doc},
|
{RPCResult::Type::STR_HEX, "txid", txid_field_doc},
|
||||||
|
14
src/rpc/rawtransaction.h
Normal file
14
src/rpc/rawtransaction.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright (c) 2017-2022 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#ifndef BITCOIN_RPC_RAWTRANSACTION_H
|
||||||
|
#define BITCOIN_RPC_RAWTRANSACTION_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
struct RPCResult;
|
||||||
|
|
||||||
|
std::vector<RPCResult> DecodeTxDoc(const std::string& txid_field_doc);
|
||||||
|
|
||||||
|
#endif // BITCOIN_RPC_RAWTRANSACTION_H
|
@ -159,6 +159,7 @@ const std::vector<std::string> RPC_COMMANDS_SAFE_FOR_FUZZING{
|
|||||||
"invalidateblock",
|
"invalidateblock",
|
||||||
"joinpsbts",
|
"joinpsbts",
|
||||||
"listbanned",
|
"listbanned",
|
||||||
|
"listmempooltransactions",
|
||||||
"listprunelocks",
|
"listprunelocks",
|
||||||
"logging",
|
"logging",
|
||||||
"maxmempool",
|
"maxmempool",
|
||||||
|
Loading…
Reference in New Issue
Block a user