aboutsummaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authorCarl Dong <contact@carldong.me>2022-07-12 22:24:31 -0400
committerCarl Dong <contact@carldong.me>2022-07-15 12:26:20 -0400
commitcb3e9a1e3f8d72daaa361fc45dd853775e754b9d (patch)
tree7d95018b6407a0fafd0d34577dd73f52d858fc21 /src/kernel
parentaa306765419f7dbea12b12e15553039835ba0e4d (diff)
downloadbitcoin-cb3e9a1e3f8d72daaa361fc45dd853775e754b9d.tar.xz
Move {Load,Dump}Mempool to kernel namespace
Also: 1. Add the newly introduced kernel/mempool_persist.cpp to IWYU CI script 2. Add chrono mapping for iwyu
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/mempool_persist.cpp189
-rw-r--r--src/kernel/mempool_persist.h28
2 files changed, 217 insertions, 0 deletions
diff --git a/src/kernel/mempool_persist.cpp b/src/kernel/mempool_persist.cpp
new file mode 100644
index 0000000000..1a1cf2bbdc
--- /dev/null
+++ b/src/kernel/mempool_persist.cpp
@@ -0,0 +1,189 @@
+// 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 <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(CTxMemPool& pool, const fs::path& load_path, CChainState& 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;
+
+ CAmount amountdelta = nFeeDelta;
+ if (amountdelta) {
+ pool.PrioritiseTransaction(tx->GetHash(), amountdelta);
+ }
+ if (nTime > TicksSinceEpoch<std::chrono::seconds>(now - pool.m_expiry)) {
+ LOCK(cs_main);
+ const auto& accepted = AcceptToMemoryPool(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(GenTxid::Txid(tx->GetHash()))) {
+ ++already_there;
+ } else {
+ ++failed;
+ }
+ }
+ } else {
+ ++expired;
+ }
+ if (ShutdownRequested())
+ return false;
+ }
+ std::map<uint256, CAmount> mapDeltas;
+ file >> mapDeltas;
+
+ 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);
+ }
+ } 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, CAmount> mapDeltas;
+ std::vector<TxMempoolInfo> vinfo;
+ std::set<uint256> 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 << int64_t{i.nFeeDelta};
+ mapDeltas.erase(i.tx->GetHash());
+ }
+
+ 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
diff --git a/src/kernel/mempool_persist.h b/src/kernel/mempool_persist.h
new file mode 100644
index 0000000000..9a15ec6dca
--- /dev/null
+++ b/src/kernel/mempool_persist.h
@@ -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 CChainState;
+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(CTxMemPool& pool, const fs::path& load_path,
+ CChainState& active_chainstate,
+ fsbridge::FopenFn mockable_fopen_function = fsbridge::fopen);
+
+} // namespace kernel
+
+
+#endif // BITCOIN_KERNEL_MEMPOOL_PERSIST_H