diff --git a/src/init.cpp b/src/init.cpp --- a/src/init.cpp +++ b/src/init.cpp @@ -237,9 +237,9 @@ g_banman.reset(); g_txindex.reset(); - if (g_is_mempool_loaded && + if (::g_mempool.IsLoaded() && gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) { - DumpMempool(); + DumpMempool(::g_mempool); } // FlushStateToDisk generates a ChainStateFlushed callback, which we should @@ -1207,9 +1207,9 @@ } } // End scope of CImportingNow if (gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) { - LoadMempool(config); + LoadMempool(config, ::g_mempool); } - g_is_mempool_loaded = !fRequestShutdown; + ::g_mempool.SetIsLoaded(!fRequestShutdown); } /** Sanity checks diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1487,7 +1487,7 @@ UniValue MempoolInfoToJSON(const CTxMemPool &pool) { UniValue ret(UniValue::VOBJ); - ret.pushKV("loaded", g_is_mempool_loaded); + ret.pushKV("loaded", pool.IsLoaded()); ret.pushKV("size", (int64_t)pool.size()); ret.pushKV("bytes", (int64_t)pool.GetTotalTxSize()); ret.pushKV("usage", (int64_t)pool.DynamicMemoryUsage()); @@ -1511,7 +1511,8 @@ "\nReturns details on the active state of the TX memory pool.\n" "\nResult:\n" "{\n" - " \"loaded\": true|false (boolean) True if the mempool is fully loaded\n" + " \"loaded\": true|false (boolean) True if the mempool is " + "fully loaded\n" " \"size\": xxxxx, (numeric) Current tx count\n" " \"bytes\": xxxxx, (numeric) Transaction size.\n" " \"usage\": xxxxx, (numeric) Total memory usage for " @@ -2199,11 +2200,11 @@ HelpExampleRpc("savemempool", "")); } - if (!g_is_mempool_loaded) { + if (!::g_mempool.IsLoaded()) { throw JSONRPCError(RPC_MISC_ERROR, "The mempool was not loaded yet"); } - if (!DumpMempool()) { + if (!DumpMempool(::g_mempool)) { throw JSONRPCError(RPC_MISC_ERROR, "Unable to dump mempool to disk"); } diff --git a/src/txmempool.h b/src/txmempool.h --- a/src/txmempool.h +++ b/src/txmempool.h @@ -496,6 +496,8 @@ void trackPackageRemoved(const CFeeRate &rate) EXCLUSIVE_LOCKS_REQUIRED(cs); + bool m_is_loaded GUARDED_BY(cs){false}; + public: // public only for testing static const int ROLLING_FEE_HALFLIFE = 60 * 60 * 12; @@ -753,6 +755,12 @@ void GetTransactionAncestry(const uint256 &txid, size_t &ancestors, size_t &descendants) const; + /** @returns true if the mempool is fully loaded */ + bool IsLoaded() const; + + /** Sets the current loaded state */ + void SetIsLoaded(bool loaded); + unsigned long size() const { LOCK(cs); return mapTx.size(); diff --git a/src/txmempool.cpp b/src/txmempool.cpp --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -1238,6 +1238,16 @@ } } +bool CTxMemPool::IsLoaded() const { + LOCK(cs); + return m_is_loaded; +} + +void CTxMemPool::SetIsLoaded(bool loaded) { + LOCK(cs); + m_is_loaded = loaded; +} + SaltedTxidHasher::SaltedTxidHasher() : k0(GetRand(std::numeric_limits::max())), k1(GetRand(std::numeric_limits::max())) {} diff --git a/src/validation.h b/src/validation.h --- a/src/validation.h +++ b/src/validation.h @@ -211,7 +211,6 @@ extern CScript COINBASE_FLAGS; extern CCriticalSection cs_main; extern CTxMemPool g_mempool; -extern std::atomic_bool g_is_mempool_loaded; extern uint64_t nLastBlockTx; extern uint64_t nLastBlockSize; extern const std::string strMessageMagic; @@ -730,9 +729,9 @@ CBlockFileInfo *GetBlockFileInfo(size_t n); /** Dump the mempool to disk. */ -bool DumpMempool(); +bool DumpMempool(const CTxMemPool &pool); /** Load the mempool from disk. */ -bool LoadMempool(const Config &config); +bool LoadMempool(const Config &config, CTxMemPool &pool); #endif // BITCOIN_VALIDATION_H diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -263,7 +263,6 @@ Amount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; CTxMemPool g_mempool; -std::atomic_bool g_is_mempool_loaded{false}; /** Constant stuff for coinbase transactions we create: */ CScript COINBASE_FLAGS; @@ -5590,7 +5589,7 @@ static const uint64_t MEMPOOL_DUMP_VERSION = 1; -bool LoadMempool(const Config &config) { +bool LoadMempool(const Config &config, CTxMemPool &pool) { int64_t nExpiryTimeout = gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60; FILE *filestr = fsbridge::fopen(GetDataDir() / "mempool.dat", "rb"); @@ -5626,14 +5625,14 @@ Amount amountdelta = nFeeDelta * SATOSHI; if (amountdelta != Amount::zero()) { - g_mempool.PrioritiseTransaction(tx->GetId(), prioritydummy, - amountdelta); + pool.PrioritiseTransaction(tx->GetId(), prioritydummy, + amountdelta); } CValidationState state; if (nTime + nExpiryTimeout > nNow) { LOCK(cs_main); AcceptToMemoryPoolWithTime( - config, g_mempool, state, tx, true /* fLimitFree */, + config, pool, state, tx, true /* fLimitFree */, nullptr /* pfMissingInputs */, nTime, false /* fOverrideMempoolLimit */, Amount::zero() /* nAbsurdFee */, false /* test_accept */); @@ -5654,7 +5653,7 @@ file >> mapDeltas; for (const auto &i : mapDeltas) { - g_mempool.PrioritiseTransaction(i.first, prioritydummy, i.second); + pool.PrioritiseTransaction(i.first, prioritydummy, i.second); } } catch (const std::exception &e) { LogPrintf("Failed to deserialize mempool data on disk: %s. Continuing " @@ -5669,7 +5668,7 @@ return true; } -bool DumpMempool() { +bool DumpMempool(const CTxMemPool &pool) { int64_t start = GetTimeMicros(); std::map mapDeltas; @@ -5679,12 +5678,12 @@ LOCK(dump_mutex); { - LOCK(g_mempool.cs); - for (const auto &i : g_mempool.mapDeltas) { + LOCK(pool.cs); + for (const auto &i : pool.mapDeltas) { mapDeltas[i.first] = i.second.second; } - vinfo = g_mempool.infoAll(); + vinfo = pool.infoAll(); } int64_t mid = GetTimeMicros();