forked from Bitcoin-ABC/bitcoin-abc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move {Load,Dump}Mempool to kernel namespace
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
Showing
9 changed files
with
258 additions
and
183 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.