aboutsummaryrefslogtreecommitdiff
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
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
-rwxr-xr-xci/test/06_script_b.sh1
-rw-r--r--contrib/devtools/iwyu/bitcoin.core.imp1
-rw-r--r--src/Makefile.am3
-rw-r--r--src/init.cpp3
-rw-r--r--src/kernel/mempool_persist.cpp189
-rw-r--r--src/kernel/mempool_persist.h28
-rw-r--r--src/rpc/mempool.cpp4
-rw-r--r--src/test/fuzz/validation_load_mempool.cpp4
-rw-r--r--src/validation.cpp156
-rw-r--r--src/validation.h6
-rwxr-xr-xtest/lint/lint-circular-dependencies.py1
11 files changed, 238 insertions, 158 deletions
diff --git a/ci/test/06_script_b.sh b/ci/test/06_script_b.sh
index e1032ba6bd..77358f93d9 100755
--- a/ci/test/06_script_b.sh
+++ b/ci/test/06_script_b.sh
@@ -41,6 +41,7 @@ if [ "${RUN_TIDY}" = "true" ]; then
CI_EXEC "python3 ${DIR_IWYU}/include-what-you-use/iwyu_tool.py"\
" src/compat"\
" src/init"\
+ " src/kernel/mempool_persist.cpp"\
" src/policy/feerate.cpp"\
" src/policy/packages.cpp"\
" src/policy/settings.cpp"\
diff --git a/contrib/devtools/iwyu/bitcoin.core.imp b/contrib/devtools/iwyu/bitcoin.core.imp
index ce7786f58c..919ffab102 100644
--- a/contrib/devtools/iwyu/bitcoin.core.imp
+++ b/contrib/devtools/iwyu/bitcoin.core.imp
@@ -3,4 +3,5 @@
{ include: [ "<bits/termios-c_lflag.h>", private, "<termios.h>", public ] },
{ include: [ "<bits/termios-struct.h>", private, "<termios.h>", public ] },
{ include: [ "<bits/termios-tcflow.h>", private, "<termios.h>", public ] },
+ { include: [ "<bits/chrono.h>", private, "<chrono>", public ] },
]
diff --git a/src/Makefile.am b/src/Makefile.am
index 1ba76ac5e7..c2148936af 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -177,6 +177,7 @@ BITCOIN_CORE_H = \
kernel/context.h \
kernel/mempool_limits.h \
kernel/mempool_options.h \
+ kernel/mempool_persist.h \
key.h \
key_io.h \
logging.h \
@@ -368,6 +369,7 @@ libbitcoin_node_a_SOURCES = \
kernel/checks.cpp \
kernel/coinstats.cpp \
kernel/context.cpp \
+ kernel/mempool_persist.cpp \
mapport.cpp \
mempool_args.cpp \
net.cpp \
@@ -884,6 +886,7 @@ libbitcoinkernel_la_SOURCES = \
kernel/checks.cpp \
kernel/coinstats.cpp \
kernel/context.cpp \
+ kernel/mempool_persist.cpp \
key.cpp \
logging.cpp \
node/blockstorage.cpp \
diff --git a/src/init.cpp b/src/init.cpp
index c46205d583..6cc42c5319 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -10,6 +10,7 @@
#include <init.h>
#include <kernel/checks.h>
+#include <kernel/mempool_persist.h>
#include <addrman.h>
#include <banman.h>
@@ -104,6 +105,8 @@
#include <zmq/zmqrpc.h>
#endif
+using kernel::DumpMempool;
+
using node::CacheSizes;
using node::CalculateCacheSizes;
using node::ChainstateLoadVerifyError;
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
diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp
index 7f4ff47941..3b53ec82e4 100644
--- a/src/rpc/mempool.cpp
+++ b/src/rpc/mempool.cpp
@@ -5,6 +5,8 @@
#include <rpc/blockchain.h>
+#include <kernel/mempool_persist.h>
+
#include <chainparams.h>
#include <core_io.h>
#include <fs.h>
@@ -19,6 +21,8 @@
#include <univalue.h>
#include <util/moneystr.h>
+using kernel::DumpMempool;
+
using node::DEFAULT_MAX_RAW_TX_FEE_RATE;
using node::MempoolPath;
using node::ShouldPersistMempool;
diff --git a/src/test/fuzz/validation_load_mempool.cpp b/src/test/fuzz/validation_load_mempool.cpp
index 357d8a9987..90c1a71d9f 100644
--- a/src/test/fuzz/validation_load_mempool.cpp
+++ b/src/test/fuzz/validation_load_mempool.cpp
@@ -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>
@@ -17,6 +19,8 @@
#include <cstdint>
#include <vector>
+using kernel::DumpMempool;
+
using node::MempoolPath;
namespace {
diff --git a/src/validation.cpp b/src/validation.cpp
index 510071de22..6840753cd4 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -5,6 +5,9 @@
#include <validation.h>
+#include <kernel/coinstats.h>
+#include <kernel/mempool_persist.h>
+
#include <arith_uint256.h>
#include <chain.h>
#include <chainparams.h>
@@ -19,7 +22,6 @@
#include <flatfile.h>
#include <fs.h>
#include <hash.h>
-#include <kernel/coinstats.h>
#include <logging.h>
#include <logging/timer.h>
#include <node/blockstorage.h>
@@ -64,6 +66,7 @@
using kernel::CCoinsStats;
using kernel::CoinStatsHashType;
using kernel::ComputeUTXOStats;
+using kernel::LoadMempool;
using fsbridge::FopenFn;
using node::BLOCKFILE_CHUNK_SIZE;
@@ -4640,157 +4643,6 @@ bool CChainState::ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size)
return ret;
}
-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;
-}
-
//! Guess how far we are in the verification process at the given block index
//! require cs_main if pindex has not been validated yet (because nChainTx might be unset)
double GuessVerificationProgress(const ChainTxData& data, const CBlockIndex *pindex) {
diff --git a/src/validation.h b/src/validation.h
index df4fc77980..f89d42e310 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -1012,12 +1012,6 @@ bool DeploymentEnabled(const ChainstateManager& chainman, DEP dep)
return DeploymentEnabled(chainman.GetConsensus(), dep);
}
-/** 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);
-
/**
* Return the expected assumeutxo value for a given height, if one exists.
*
diff --git a/test/lint/lint-circular-dependencies.py b/test/lint/lint-circular-dependencies.py
index 5d157eb4b1..f44ed8f7c7 100755
--- a/test/lint/lint-circular-dependencies.py
+++ b/test/lint/lint-circular-dependencies.py
@@ -22,6 +22,7 @@ EXPECTED_CIRCULAR_DEPENDENCIES = (
"wallet/fees -> wallet/wallet -> wallet/fees",
"wallet/wallet -> wallet/walletdb -> wallet/wallet",
"kernel/coinstats -> validation -> kernel/coinstats",
+ "kernel/mempool_persist -> validation -> kernel/mempool_persist",
)
CODE_DIR = "src"