mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-10 14:48:46 +02:00
Add importmempool RPC
test_importmempool_union contributed by glozow Co-authored-by: glozow <gloriajzhao@gmail.com>
This commit is contained in:
@@ -52,7 +52,7 @@ bool LoadMempool(CTxMemPool& pool, const fs::path& load_path, Chainstate& active
|
||||
int64_t failed = 0;
|
||||
int64_t already_there = 0;
|
||||
int64_t unbroadcast = 0;
|
||||
auto now = NodeClock::now();
|
||||
const auto now{NodeClock::now()};
|
||||
|
||||
try {
|
||||
uint64_t version;
|
||||
@@ -71,8 +71,12 @@ bool LoadMempool(CTxMemPool& pool, const fs::path& load_path, Chainstate& active
|
||||
file >> nTime;
|
||||
file >> nFeeDelta;
|
||||
|
||||
if (opts.use_current_time) {
|
||||
nTime = TicksSinceEpoch<std::chrono::seconds>(now);
|
||||
}
|
||||
|
||||
CAmount amountdelta = nFeeDelta;
|
||||
if (amountdelta) {
|
||||
if (amountdelta && opts.apply_fee_delta_priority) {
|
||||
pool.PrioritiseTransaction(tx->GetHash(), amountdelta);
|
||||
}
|
||||
if (nTime > TicksSinceEpoch<std::chrono::seconds>(now - pool.m_expiry)) {
|
||||
@@ -100,17 +104,21 @@ bool LoadMempool(CTxMemPool& pool, const fs::path& load_path, Chainstate& active
|
||||
std::map<uint256, CAmount> mapDeltas;
|
||||
file >> mapDeltas;
|
||||
|
||||
for (const auto& i : mapDeltas) {
|
||||
pool.PrioritiseTransaction(i.first, i.second);
|
||||
if (opts.apply_fee_delta_priority) {
|
||||
for (const auto& i : mapDeltas) {
|
||||
pool.PrioritiseTransaction(i.first, i.second);
|
||||
}
|
||||
}
|
||||
|
||||
std::set<uint256> unbroadcast_txids;
|
||||
file >> unbroadcast_txids;
|
||||
unbroadcast = unbroadcast_txids.size();
|
||||
for (const auto& txid : unbroadcast_txids) {
|
||||
// Ensure transactions were accepted to mempool then add to
|
||||
// unbroadcast set.
|
||||
if (pool.get(txid) != nullptr) pool.AddUnbroadcastTx(txid);
|
||||
if (opts.apply_unbroadcast_set) {
|
||||
unbroadcast = unbroadcast_txids.size();
|
||||
for (const auto& txid : unbroadcast_txids) {
|
||||
// Ensure transactions were accepted to mempool then add to
|
||||
// unbroadcast set.
|
||||
if (pool.get(txid) != nullptr) pool.AddUnbroadcastTx(txid);
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
LogPrintf("Failed to deserialize mempool data on disk: %s. Continuing anyway.\n", e.what());
|
||||
|
||||
@@ -19,6 +19,9 @@ bool DumpMempool(const CTxMemPool& pool, const fs::path& dump_path,
|
||||
|
||||
struct ImportMempoolOptions {
|
||||
fsbridge::FopenFn mockable_fopen_function{fsbridge::fopen};
|
||||
bool use_current_time{false};
|
||||
bool apply_fee_delta_priority{true};
|
||||
bool apply_unbroadcast_set{true};
|
||||
};
|
||||
/** Import the file and attempt to add its contents to the mempool. */
|
||||
bool LoadMempool(CTxMemPool& pool, const fs::path& load_path,
|
||||
|
||||
@@ -229,6 +229,10 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
||||
{ "importaddress", 2, "rescan" },
|
||||
{ "importaddress", 3, "p2sh" },
|
||||
{ "importpubkey", 2, "rescan" },
|
||||
{ "importmempool", 1, "options" },
|
||||
{ "importmempool", 1, "apply_fee_delta_priority" },
|
||||
{ "importmempool", 1, "use_current_time" },
|
||||
{ "importmempool", 1, "apply_unbroadcast_set" },
|
||||
{ "importmulti", 0, "requests" },
|
||||
{ "importmulti", 1, "options" },
|
||||
{ "importmulti", 1, "rescan" },
|
||||
|
||||
@@ -719,6 +719,66 @@ static RPCHelpMan getmempoolinfo()
|
||||
};
|
||||
}
|
||||
|
||||
static RPCHelpMan importmempool()
|
||||
{
|
||||
return RPCHelpMan{
|
||||
"importmempool",
|
||||
"Import a mempool.dat file and attempt to add its contents to the mempool.\n"
|
||||
"Warning: Importing untrusted files is dangerous, especially if metadata from the file is taken over.",
|
||||
{
|
||||
{"filepath", RPCArg::Type::STR, RPCArg::Optional::NO, "The mempool file"},
|
||||
{"options",
|
||||
RPCArg::Type::OBJ_NAMED_PARAMS,
|
||||
RPCArg::Optional::OMITTED,
|
||||
"",
|
||||
{
|
||||
{"use_current_time", RPCArg::Type::BOOL, RPCArg::Default{true},
|
||||
"Whether to use the current system time or use the entry time metadata from the mempool file.\n"
|
||||
"Warning: Importing untrusted metadata may lead to unexpected issues and undesirable behavior."},
|
||||
{"apply_fee_delta_priority", RPCArg::Type::BOOL, RPCArg::Default{false},
|
||||
"Whether to apply the fee delta metadata from the mempool file.\n"
|
||||
"It will be added to any existing fee deltas.\n"
|
||||
"The fee delta can be set by the prioritisetransaction RPC.\n"
|
||||
"Warning: Importing untrusted metadata may lead to unexpected issues and undesirable behavior.\n"
|
||||
"Only set this bool if you understand what it does."},
|
||||
{"apply_unbroadcast_set", RPCArg::Type::BOOL, RPCArg::Default{false},
|
||||
"Whether to apply the unbroadcast set metadata from the mempool file.\n"
|
||||
"Warning: Importing untrusted metadata may lead to unexpected issues and undesirable behavior."},
|
||||
},
|
||||
RPCArgOptions{.oneline_description = "\"options\""}},
|
||||
},
|
||||
RPCResult{RPCResult::Type::OBJ, "", "", std::vector<RPCResult>{}},
|
||||
RPCExamples{HelpExampleCli("importmempool", "/path/to/mempool.dat") + HelpExampleRpc("importmempool", "/path/to/mempool.dat")},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
|
||||
const NodeContext& node{EnsureAnyNodeContext(request.context)};
|
||||
|
||||
CTxMemPool& mempool{EnsureMemPool(node)};
|
||||
Chainstate& chainstate = EnsureChainman(node).ActiveChainstate();
|
||||
|
||||
if (chainstate.IsInitialBlockDownload()) {
|
||||
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Can only import the mempool after the block download and sync is done.");
|
||||
}
|
||||
|
||||
const fs::path load_path{fs::u8path(request.params[0].get_str())};
|
||||
const UniValue& use_current_time{request.params[1]["use_current_time"]};
|
||||
const UniValue& apply_fee_delta{request.params[1]["apply_fee_delta_priority"]};
|
||||
const UniValue& apply_unbroadcast{request.params[1]["apply_unbroadcast_set"]};
|
||||
kernel::ImportMempoolOptions opts{
|
||||
.use_current_time = use_current_time.isNull() ? true : use_current_time.get_bool(),
|
||||
.apply_fee_delta_priority = apply_fee_delta.isNull() ? false : apply_fee_delta.get_bool(),
|
||||
.apply_unbroadcast_set = apply_unbroadcast.isNull() ? false : apply_unbroadcast.get_bool(),
|
||||
};
|
||||
|
||||
if (!kernel::LoadMempool(mempool, load_path, chainstate, std::move(opts))) {
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "Unable to import mempool file, see debug.log for details.");
|
||||
}
|
||||
|
||||
UniValue ret{UniValue::VOBJ};
|
||||
return ret;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static RPCHelpMan savemempool()
|
||||
{
|
||||
return RPCHelpMan{"savemempool",
|
||||
@@ -921,6 +981,7 @@ void RegisterMempoolRPCCommands(CRPCTable& t)
|
||||
{"blockchain", &gettxspendingprevout},
|
||||
{"blockchain", &getmempoolinfo},
|
||||
{"blockchain", &getrawmempool},
|
||||
{"blockchain", &importmempool},
|
||||
{"blockchain", &savemempool},
|
||||
{"hidden", &submitpackage},
|
||||
};
|
||||
|
||||
@@ -78,6 +78,7 @@ const std::vector<std::string> RPC_COMMANDS_NOT_SAFE_FOR_FUZZING{
|
||||
"generatetoaddress", // avoid prohibitively slow execution (when `num_blocks` is large)
|
||||
"generatetodescriptor", // avoid prohibitively slow execution (when `nblocks` is large)
|
||||
"gettxoutproof", // avoid prohibitively slow execution
|
||||
"importmempool", // avoid reading from disk
|
||||
"importwallet", // avoid reading from disk
|
||||
"loadwallet", // avoid reading from disk
|
||||
"savemempool", // disabled as a precautionary measure: may take a file path argument in the future
|
||||
|
||||
Reference in New Issue
Block a user