Bitcoin ABC 0.26.3
P2P Digital Currency
Loading...
Searching...
No Matches
mempool_persist.cpp
Go to the documentation of this file.
1// Copyright (c) 2022 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
6
7#include <clientversion.h>
8#include <consensus/amount.h>
9#include <logging.h>
11#include <serialize.h>
12#include <shutdown.h>
13#include <streams.h>
14#include <sync.h>
15#include <txmempool.h>
16#include <uint256.h>
17#include <util/fs.h>
18#include <util/fs_helpers.h>
19#include <util/time.h>
20#include <validation.h>
21
22#include <chrono>
23#include <cstdint>
24#include <cstdio>
25#include <exception>
26#include <functional>
27#include <map>
28#include <memory>
29#include <set>
30#include <stdexcept>
31#include <utility>
32#include <vector>
33
35
36namespace kernel {
38
42 if (load_path.empty()) {
43 return false;
44 }
45
48 if (file.IsNull()) {
50 "Failed to open mempool file from disk. Continuing anyway.\n");
51 return false;
52 }
53
54 int64_t count = 0;
55 int64_t expired = 0;
56 int64_t failed = 0;
59 auto now = NodeClock::now();
60
61 try {
62 uint64_t version;
63 file >> version;
64 if (version != MEMPOOL_DUMP_VERSION) {
65 return false;
66 }
67
69 file >> num;
70 while (num) {
71 --num;
73 int64_t nTime;
74 int64_t nFeeDelta;
75 file >> tx;
76 file >> nTime;
77 file >> nFeeDelta;
78
79 Amount amountdelta = nFeeDelta * SATOSHI;
80 if (amountdelta != Amount::zero()) {
81 pool.PrioritiseTransaction(tx->GetId(), amountdelta);
82 }
83 if (nTime >
86 const auto &accepted =
88 /*bypass_limits=*/false,
89 /*test_accept=*/false);
90 if (accepted.m_result_type ==
92 ++count;
93 } else {
94 // mempool may contain the transaction already, e.g. from
95 // wallet(s) having loaded it while we were processing
96 // mempool transactions; consider these as valid, instead of
97 // failed, but mark them as 'already there'
98 if (pool.exists(tx->GetId())) {
100 } else {
101 ++failed;
102 }
103 }
104 } else {
105 ++expired;
106 }
107
108 if (ShutdownRequested()) {
109 return false;
110 }
111 }
112 std::map<TxId, Amount> mapDeltas;
113 file >> mapDeltas;
114
115 for (const auto &i : mapDeltas) {
116 pool.PrioritiseTransaction(i.first, i.second);
117 }
118
119 std::set<TxId> unbroadcast_txids;
120 file >> unbroadcast_txids;
122 for (const auto &txid : unbroadcast_txids) {
123 // Ensure transactions were accepted to mempool then add to
124 // unbroadcast set.
125 if (pool.get(txid) != nullptr) {
126 pool.AddUnbroadcastTx(txid);
127 }
128 }
129 } catch (const std::exception &e) {
130 LogPrintf("Failed to deserialize mempool data on disk: %s. Continuing "
131 "anyway.\n",
132 e.what());
133 return false;
134 }
135
136 LogPrintf("Imported mempool transactions from disk: %i succeeded, %i "
137 "failed, %i expired, %i already there, %i waiting for initial "
138 "broadcast\n",
140 return true;
141}
142
143bool DumpMempool(const CTxMemPool &pool, const fs::path &dump_path,
145 auto start = SteadyClock::now();
146
147 std::map<uint256, Amount> mapDeltas;
148 std::vector<TxMempoolInfo> vinfo;
149 std::set<TxId> unbroadcast_txids;
150
151 static Mutex dump_mutex;
153
154 {
155 LOCK(pool.cs);
156 for (const auto &i : pool.mapDeltas) {
157 mapDeltas[i.first] = i.second;
158 }
159
160 vinfo = pool.infoAll();
162 }
163
164 auto mid = SteadyClock::now();
165
166 try {
168 if (!filestr) {
169 return false;
170 }
171
173
175 file << version;
176
177 file << uint64_t(vinfo.size());
178 for (const auto &i : vinfo) {
179 file << *(i.tx);
180 file << int64_t(count_seconds(i.m_time));
181 file << i.nFeeDelta;
182 mapDeltas.erase(i.tx->GetId());
183 }
184
185 file << mapDeltas;
186
187 LogPrintf("Writing %d unbroadcast transactions to disk.\n",
188 unbroadcast_txids.size());
189 file << unbroadcast_txids;
190
191 if (!skip_file_commit && !FileCommit(file.Get())) {
192 throw std::runtime_error("FileCommit failed");
193 }
194 file.fclose();
195 if (!RenameOver(dump_path + ".new", dump_path)) {
196 throw std::runtime_error("Rename failed");
197 }
198 auto last = SteadyClock::now();
199
200 LogPrintf("Dumped mempool: %gs to copy, %gs to dump\n",
201 Ticks<SecondsDouble>(mid - start),
202 Ticks<SecondsDouble>(last - mid));
203 } catch (const std::exception &e) {
204 LogPrintf("Failed to dump mempool: %s. Continuing anyway.\n", e.what());
205 return false;
206 }
207 return true;
208}
209
210} // namespace kernel
static constexpr Amount SATOSHI
Definition amount.h:143
bool IsNull() const
Return true if the wrapped FILE* is nullptr, false otherwise.
Definition streams.h:570
FILE * Get() const
Get wrapped FILE* without transfer of ownership.
Definition streams.h:567
int fclose()
Definition streams.h:541
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition txmempool.h:212
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
Definition txmempool.h:307
const std::chrono::seconds m_expiry
Definition txmempool.h:345
std::vector< TxMempoolInfo > infoAll() const
bool exists(const TxId &txid) const
Definition txmempool.h:503
std::set< TxId > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
Definition txmempool.h:540
CTransactionRef get(const TxId &txid) const
void PrioritiseTransaction(const TxId &txid, const Amount nFeeDelta)
Affect CreateNewBlock prioritisation of transactions.
void AddUnbroadcastTx(const TxId &txid)
Adds a transaction to the unbroadcast set.
Definition txmempool.h:527
Chainstate stores and provides an API to update our local knowledge of the current best chain.
Definition validation.h:699
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition fs.h:30
static constexpr int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition cs_main.cpp:7
bool RenameOver(fs::path src, fs::path dest)
bool FileCommit(FILE *file)
Ensure file contents are fully committed to disk, using a platform-specific feature analogous to fsyn...
#define LogPrintf(...)
Definition logging.h:207
std::function< FILE *(const fs::path &, const char *)> FopenFn
Definition fs.h:198
bool DumpMempool(const CTxMemPool &pool, const fs::path &dump_path, FopenFn mockable_fopen_function, bool skip_file_commit)
static const uint64_t MEMPOOL_DUMP_VERSION
bool LoadMempool(CTxMemPool &pool, const fs::path &load_path, Chainstate &active_chainstate, FopenFn mockable_fopen_function)
std::shared_ptr< const CTransaction > CTransactionRef
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
Definition random.h:85
@ SER_DISK
Definition serialize.h:153
bool ShutdownRequested()
Returns true if a shutdown is requested, false otherwise.
Definition shutdown.cpp:85
static constexpr Amount zero() noexcept
Definition amount.h:32
@ VALID
Fully validated, valid.
static time_point now() noexcept
Return current system time or mocked time, if set.
Definition time.cpp:71
#define LOCK(cs)
Definition sync.h:306
static int count
Definition tests.c:31
constexpr int64_t count_seconds(std::chrono::seconds t)
Definition time.h:55
MempoolAcceptResult AcceptToMemoryPool(Chainstate &active_chainstate, const CTransactionRef &tx, int64_t accept_time, bool bypass_limits, bool test_accept, unsigned int heightOverride)
Try to add a transaction to the mempool.