Skip to content

Commit

Permalink
Move {Load,Dump}Mempool to kernel namespace
Browse files Browse the repository at this point in the history
Summary:
This is mostly moving code. Can be checked with  `git show --color-moved=dimmed-zebra --color-moved-ws=ignore-all-space`

This concludes backport of [[bitcoin/bitcoin#25487 | core#25487]]
bitcoin/bitcoin@cb3e9a1

Depends on D15723

Test Plan:
```
cmake .. -GNinja -DBUILD_BITCOIN_CHAINSTATE=ON

ninja all check-all bitcoin-fuzzers
```

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Differential Revision: https://reviews.bitcoinabc.org/D15724
  • Loading branch information
dongcarl authored and PiRK committed Mar 18, 2024
1 parent c228466 commit 6abd811
Show file tree
Hide file tree
Showing 9 changed files with 258 additions and 183 deletions.
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ add_library(server
init.cpp
init/common.cpp
invrequest.cpp
kernel/mempool_persist.cpp
mapport.cpp
mempool_args.cpp
minerfund.cpp
Expand Down Expand Up @@ -834,6 +835,7 @@ if(BUILD_BITCOIN_CHAINSTATE)
# like index/*.cpp will be removed.
add_library(bitcoinkernel
kernel/bitcoinkernel.cpp
kernel/mempool_persist.cpp
arith_uint256.cpp
blockfileinfo.cpp
blockfilter.cpp
Expand Down
4 changes: 4 additions & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

#include <init.h>

#include <kernel/mempool_persist.h>

#include <addrman.h>
#include <avalanche/avalanche.h>
#include <avalanche/processor.h>
Expand Down Expand Up @@ -103,6 +105,8 @@
#include <thread>
#include <vector>

using kernel::DumpMempool;

using node::CacheSizes;
using node::CalculateCacheSizes;
using node::CleanupBlockRevFiles;
Expand Down
211 changes: 211 additions & 0 deletions src/kernel/mempool_persist.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
// Copyright (c) 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.

#include <kernel/mempool_persist.h>

#include <clientversion.h>
#include <config.h>
#include <consensus/amount.h>
#include <fs.h>
#include <logging.h>
#include <primitives/transaction.h>
#include <serialize.h>
#include <shutdown.h>
#include <streams.h>
#include <sync.h>
#include <txmempool.h>
#include <uint256.h>
#include <util/system.h>
#include <util/time.h>
#include <validation.h>

#include <chrono>
#include <cstdint>
#include <cstdio>
#include <exception>
#include <functional>
#include <map>
#include <memory>
#include <set>
#include <stdexcept>
#include <utility>
#include <vector>

using fsbridge::FopenFn;

namespace kernel {
static const uint64_t MEMPOOL_DUMP_VERSION = 1;

bool LoadMempool(const Config &config, CTxMemPool &pool,
const fs::path &load_path, Chainstate &active_chainstate,
FopenFn mockable_fopen_function) {
if (load_path.empty()) {
return false;
}

FILE *filestr{mockable_fopen_function(load_path, "rb")};
CAutoFile file(filestr, SER_DISK, CLIENT_VERSION);
if (file.IsNull()) {
LogPrintf(
"Failed to open mempool file from disk. Continuing anyway.\n");
return false;
}

int64_t count = 0;
int64_t expired = 0;
int64_t failed = 0;
int64_t already_there = 0;
int64_t unbroadcast = 0;
auto now = NodeClock::now();

try {
uint64_t version;
file >> version;
if (version != MEMPOOL_DUMP_VERSION) {
return false;
}

uint64_t num;
file >> num;
while (num) {
--num;
CTransactionRef tx;
int64_t nTime;
int64_t nFeeDelta;
file >> tx;
file >> nTime;
file >> nFeeDelta;

Amount amountdelta = nFeeDelta * SATOSHI;
if (amountdelta != Amount::zero()) {
pool.PrioritiseTransaction(tx->GetId(), amountdelta);
}
if (nTime >
TicksSinceEpoch<std::chrono::seconds>(now - pool.m_expiry)) {
LOCK(cs_main);
const auto &accepted =
AcceptToMemoryPool(config, active_chainstate, tx, nTime,
/*bypass_limits=*/false,
/*test_accept=*/false);
if (accepted.m_result_type ==
MempoolAcceptResult::ResultType::VALID) {
++count;
} else {
// mempool may contain the transaction already, e.g. from
// wallet(s) having loaded it while we were processing
// mempool transactions; consider these as valid, instead of
// failed, but mark them as 'already there'
if (pool.exists(tx->GetId())) {
++already_there;
} else {
++failed;
}
}
} else {
++expired;
}

if (ShutdownRequested()) {
return false;
}
}
std::map<TxId, Amount> mapDeltas;
file >> mapDeltas;

for (const auto &i : mapDeltas) {
pool.PrioritiseTransaction(i.first, i.second);
}

std::set<TxId> 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);
}
}
} catch (const std::exception &e) {
LogPrintf("Failed to deserialize mempool data on disk: %s. Continuing "
"anyway.\n",
e.what());
return false;
}

LogPrintf("Imported mempool transactions from disk: %i succeeded, %i "
"failed, %i expired, %i already there, %i waiting for initial "
"broadcast\n",
count, failed, expired, already_there, unbroadcast);
return true;
}

bool DumpMempool(const CTxMemPool &pool, const fs::path &dump_path,
FopenFn mockable_fopen_function, bool skip_file_commit) {
auto start = SteadyClock::now();

std::map<uint256, Amount> mapDeltas;
std::vector<TxMempoolInfo> vinfo;
std::set<TxId> unbroadcast_txids;

static Mutex dump_mutex;
LOCK(dump_mutex);

{
LOCK(pool.cs);
for (const auto &i : pool.mapDeltas) {
mapDeltas[i.first] = i.second;
}

vinfo = pool.infoAll();
unbroadcast_txids = pool.GetUnbroadcastTxs();
}

auto mid = SteadyClock::now();

try {
FILE *filestr{mockable_fopen_function(dump_path + ".new", "wb")};
if (!filestr) {
return false;
}

CAutoFile file(filestr, SER_DISK, CLIENT_VERSION);

uint64_t version = MEMPOOL_DUMP_VERSION;
file << version;

file << uint64_t(vinfo.size());
for (const auto &i : vinfo) {
file << *(i.tx);
file << int64_t(count_seconds(i.m_time));
file << i.nFeeDelta;
mapDeltas.erase(i.tx->GetId());
}

file << mapDeltas;

LogPrintf("Writing %d unbroadcast transactions to disk.\n",
unbroadcast_txids.size());
file << unbroadcast_txids;

if (!skip_file_commit && !FileCommit(file.Get())) {
throw std::runtime_error("FileCommit failed");
}
file.fclose();
if (!RenameOver(dump_path + ".new", dump_path)) {
throw std::runtime_error("Rename failed");
}
auto last = SteadyClock::now();

LogPrintf("Dumped mempool: %gs to copy, %gs to dump\n",
Ticks<SecondsDouble>(mid - start),
Ticks<SecondsDouble>(last - mid));
} catch (const std::exception &e) {
LogPrintf("Failed to dump mempool: %s. Continuing anyway.\n", e.what());
return false;
}
return true;
}

} // namespace kernel
28 changes: 28 additions & 0 deletions src/kernel/mempool_persist.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) 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_KERNEL_MEMPOOL_PERSIST_H
#define BITCOIN_KERNEL_MEMPOOL_PERSIST_H

#include <fs.h>

class Chainstate;
class Config;
class CTxMemPool;

namespace kernel {

/** Dump the mempool to disk. */
bool DumpMempool(const CTxMemPool &pool, const fs::path &dump_path,
fsbridge::FopenFn mockable_fopen_function = fsbridge::fopen,
bool skip_file_commit = false);

/** Load the mempool from disk. */
bool LoadMempool(const Config &config, CTxMemPool &pool,
const fs::path &load_path, Chainstate &active_chainstate,
fsbridge::FopenFn mockable_fopen_function = fsbridge::fopen);

} // namespace kernel

#endif // BITCOIN_KERNEL_MEMPOOL_PERSIST_H
4 changes: 4 additions & 0 deletions src/rpc/mempool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <kernel/mempool_persist.h>

#include <core_io.h>
#include <fs.h>
#include <node/context.h>
Expand All @@ -16,6 +18,8 @@
#include <univalue.h>
#include <validation.h>

using kernel::DumpMempool;

using node::MempoolPath;
using node::NodeContext;
using node::ShouldPersistMempool;
Expand Down
4 changes: 4 additions & 0 deletions src/test/fuzz/validation_load_mempool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <kernel/mempool_persist.h>

#include <chainparamsbase.h>
#include <mempool_args.h>
#include <node/mempool_persist_args.h>
Expand All @@ -17,6 +19,8 @@
#include <cstdint>
#include <vector>

using kernel::DumpMempool;

using node::MempoolPath;

namespace {
Expand Down
Loading

0 comments on commit 6abd811

Please sign in to comment.