|
|
|
@ -6935,6 +6935,119 @@ int VersionBitsTipStateSinceHeight(const Consensus::Params& params, Consensus::D
|
|
|
|
|
return VersionBitsStateSinceHeight(chainActive.Tip(), params, pos, versionbitscache);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const uint64_t MEMPOOL_DUMP_VERSION = 1;
|
|
|
|
|
|
|
|
|
|
bool LoadMempool(void)
|
|
|
|
|
{
|
|
|
|
|
int64_t nExpiryTimeout = GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60;
|
|
|
|
|
FILE* filestr = fopen((GetDataDir() / "mempool.dat").string().c_str(), "r");
|
|
|
|
|
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 skipped = 0;
|
|
|
|
|
int64_t failed = 0;
|
|
|
|
|
int64_t nNow = GetTime();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
uint64_t version;
|
|
|
|
|
file >> version;
|
|
|
|
|
if (version != MEMPOOL_DUMP_VERSION) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
uint64_t num;
|
|
|
|
|
file >> num;
|
|
|
|
|
double prioritydummy = 0;
|
|
|
|
|
while (num--) {
|
|
|
|
|
CTransaction tx;
|
|
|
|
|
int64_t nTime;
|
|
|
|
|
int64_t nFeeDelta;
|
|
|
|
|
file >> tx;
|
|
|
|
|
file >> nTime;
|
|
|
|
|
file >> nFeeDelta;
|
|
|
|
|
|
|
|
|
|
CAmount amountdelta = nFeeDelta;
|
|
|
|
|
if (amountdelta) {
|
|
|
|
|
mempool.PrioritiseTransaction(tx.GetHash(), tx.GetHash().ToString(), prioritydummy, amountdelta);
|
|
|
|
|
}
|
|
|
|
|
CValidationState state;
|
|
|
|
|
if (nTime + nExpiryTimeout > nNow) {
|
|
|
|
|
LOCK(cs_main);
|
|
|
|
|
AcceptToMemoryPoolWithTime(mempool, state, tx, true, NULL, nTime);
|
|
|
|
|
if (state.IsValid()) {
|
|
|
|
|
++count;
|
|
|
|
|
} else {
|
|
|
|
|
++failed;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
++skipped;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
std::map<uint256, CAmount> mapDeltas;
|
|
|
|
|
file >> mapDeltas;
|
|
|
|
|
|
|
|
|
|
for (const auto& i : mapDeltas) {
|
|
|
|
|
mempool.PrioritiseTransaction(i.first, i.first.ToString(), prioritydummy, i.second);
|
|
|
|
|
}
|
|
|
|
|
} 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 successes, %i failed, %i expired\n", count, failed, skipped);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DumpMempool(void)
|
|
|
|
|
{
|
|
|
|
|
int64_t start = GetTimeMicros();
|
|
|
|
|
|
|
|
|
|
std::map<uint256, CAmount> mapDeltas;
|
|
|
|
|
std::vector<TxMempoolInfo> vinfo;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
LOCK(mempool.cs);
|
|
|
|
|
for (const auto &i : mempool.mapDeltas) {
|
|
|
|
|
mapDeltas[i.first] = i.second.first;
|
|
|
|
|
}
|
|
|
|
|
vinfo = mempool.infoAll();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64_t mid = GetTimeMicros();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
FILE* filestr = fopen((GetDataDir() / "mempool.dat.new").string().c_str(), "w");
|
|
|
|
|
if (!filestr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)i.nTime;
|
|
|
|
|
file << (int64_t)i.nFeeDelta;
|
|
|
|
|
mapDeltas.erase(i.tx->GetHash());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
file << mapDeltas;
|
|
|
|
|
FileCommit(file.Get());
|
|
|
|
|
file.fclose();
|
|
|
|
|
RenameOver(GetDataDir() / "mempool.dat.new", GetDataDir() / "mempool.dat");
|
|
|
|
|
int64_t last = GetTimeMicros();
|
|
|
|
|
LogPrintf("Dumped mempool: %gs to copy, %gs to dump\n", (mid-start)*0.000001, (last-mid)*0.000001);
|
|
|
|
|
} catch (const std::exception& e) {
|
|
|
|
|
LogPrintf("Failed to dump mempool: %s. Continuing anyway.\n", e.what());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class CMainCleanup
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|