|
|
|
@ -1135,7 +1135,7 @@ std::string FormatStateMessage(const CValidationState &state)
@@ -1135,7 +1135,7 @@ std::string FormatStateMessage(const CValidationState &state)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const CTransaction& tx, bool fLimitFree, |
|
|
|
|
bool* pfMissingInputs, bool fOverrideMempoolLimit, const CAmount& nAbsurdFee, |
|
|
|
|
bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit, const CAmount& nAbsurdFee, |
|
|
|
|
std::vector<uint256>& vHashTxnToUncache) |
|
|
|
|
{ |
|
|
|
|
const uint256 hash = tx.GetHash(); |
|
|
|
@ -1308,7 +1308,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
@@ -1308,7 +1308,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), pool.HasNoInputsOf(tx), inChainInputValue, fSpendsCoinbase, nSigOpsCost, lp); |
|
|
|
|
CTxMemPoolEntry entry(tx, nFees, nAcceptTime, dPriority, chainActive.Height(), pool.HasNoInputsOf(tx), inChainInputValue, fSpendsCoinbase, nSigOpsCost, lp); |
|
|
|
|
unsigned int nSize = entry.GetTxSize(); |
|
|
|
|
|
|
|
|
|
// Check that the transaction doesn't have an excessive number of
|
|
|
|
@ -1572,11 +1572,11 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
@@ -1572,11 +1572,11 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, |
|
|
|
|
bool* pfMissingInputs, bool fOverrideMempoolLimit, const CAmount nAbsurdFee) |
|
|
|
|
bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, |
|
|
|
|
bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit, const CAmount nAbsurdFee) |
|
|
|
|
{ |
|
|
|
|
std::vector<uint256> vHashTxToUncache; |
|
|
|
|
bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, fOverrideMempoolLimit, nAbsurdFee, vHashTxToUncache); |
|
|
|
|
bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, fOverrideMempoolLimit, nAbsurdFee, vHashTxToUncache); |
|
|
|
|
if (!res) { |
|
|
|
|
BOOST_FOREACH(const uint256& hashTx, vHashTxToUncache) |
|
|
|
|
pcoinsTip->Uncache(hashTx); |
|
|
|
@ -1584,6 +1584,12 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
@@ -1584,6 +1584,12 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|
|
|
|
return res; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, |
|
|
|
|
bool* pfMissingInputs, bool fOverrideMempoolLimit, const CAmount nAbsurdFee) |
|
|
|
|
{ |
|
|
|
|
return AcceptToMemoryPoolWithTime(pool, state, tx, fLimitFree, pfMissingInputs, GetTime(), fOverrideMempoolLimit, nAbsurdFee); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock */ |
|
|
|
|
bool GetTransaction(const uint256 &hash, CTransaction &txOut, const Consensus::Params& consensusParams, uint256 &hashBlock, bool fAllowSlow) |
|
|
|
|
{ |
|
|
|
@ -6929,6 +6935,119 @@ int VersionBitsTipStateSinceHeight(const Consensus::Params& params, Consensus::D
@@ -6929,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: |
|
|
|
|