mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-18 13:17:55 +02:00
Merge 821f5c824f into merged_master (Bitcoin PR bitcoin/bitcoin#25487)
This commit is contained in:
commit
076e809b74
23 changed files with 373 additions and 195 deletions
|
|
@ -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>
|
||||
|
|
@ -17,8 +20,8 @@
|
|||
#include <consensus/validation.h>
|
||||
#include <cuckoocache.h>
|
||||
#include <flatfile.h>
|
||||
#include <fs.h>
|
||||
#include <hash.h>
|
||||
#include <kernel/coinstats.h>
|
||||
#include <logging.h>
|
||||
#include <logging/timer.h>
|
||||
#include <mainchainrpc.h>
|
||||
|
|
@ -50,6 +53,7 @@
|
|||
#include <util/rbf.h>
|
||||
#include <util/strencodings.h>
|
||||
#include <util/system.h>
|
||||
#include <util/time.h>
|
||||
#include <util/trace.h>
|
||||
#include <util/translation.h>
|
||||
#include <validationinterface.h>
|
||||
|
|
@ -60,6 +64,7 @@
|
|||
#include <dynafed.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <deque>
|
||||
#include <numeric>
|
||||
#include <optional>
|
||||
|
|
@ -68,7 +73,9 @@
|
|||
using kernel::CCoinsStats;
|
||||
using kernel::CoinStatsHashType;
|
||||
using kernel::ComputeUTXOStats;
|
||||
using kernel::LoadMempool;
|
||||
|
||||
using fsbridge::FopenFn;
|
||||
using node::BLOCKFILE_CHUNK_SIZE;
|
||||
using node::BlockManager;
|
||||
using node::BlockMap;
|
||||
|
|
@ -4329,13 +4336,11 @@ void PruneBlockFilesManual(CChainState& active_chainstate, int nManualPruneHeigh
|
|||
}
|
||||
}
|
||||
|
||||
void CChainState::LoadMempool(const ArgsManager& args)
|
||||
void CChainState::LoadMempool(const fs::path& load_path, FopenFn mockable_fopen_function)
|
||||
{
|
||||
if (!m_mempool) return;
|
||||
if (args.GetBoolArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
|
||||
::LoadMempool(*m_mempool, *this);
|
||||
}
|
||||
m_mempool->SetIsLoaded(!ShutdownRequested());
|
||||
::LoadMempool(*m_mempool, load_path, *this, mockable_fopen_function);
|
||||
m_mempool->SetLoadTried(!ShutdownRequested());
|
||||
}
|
||||
|
||||
bool CChainState::LoadChainTip()
|
||||
|
|
@ -5107,152 +5112,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, CChainState& active_chainstate, FopenFn mockable_fopen_function)
|
||||
{
|
||||
int64_t nExpiryTimeout = std::chrono::seconds{pool.m_expiry}.count();
|
||||
FILE* filestr{mockable_fopen_function(gArgs.GetDataDirNet() / "mempool.dat", "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;
|
||||
int64_t nNow = GetTime();
|
||||
|
||||
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 > nNow - nExpiryTimeout) {
|
||||
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, FopenFn mockable_fopen_function, bool skip_file_commit)
|
||||
{
|
||||
int64_t start = GetTimeMicros();
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
int64_t mid = GetTimeMicros();
|
||||
|
||||
try {
|
||||
FILE* filestr{mockable_fopen_function(gArgs.GetDataDirNet() / "mempool.dat.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(gArgs.GetDataDirNet() / "mempool.dat.new", gArgs.GetDataDirNet() / "mempool.dat")) {
|
||||
throw std::runtime_error("Rename failed");
|
||||
}
|
||||
int64_t last = GetTimeMicros();
|
||||
LogPrintf("Dumped mempool: %gs to copy, %gs to dump\n", (mid-start)*MICRO, (last-mid)*MICRO);
|
||||
} 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.
|
||||
//! Since we have signed fixed-interval blocks, estimating progress is a very easy.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue