aboutsummaryrefslogtreecommitdiff
path: root/src/validation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/validation.cpp')
-rw-r--r--src/validation.cpp51
1 files changed, 37 insertions, 14 deletions
diff --git a/src/validation.cpp b/src/validation.cpp
index b36e90112..37a4186e0 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -525,10 +525,23 @@ std::string FormatStateMessage(const CValidationState &state)
state.GetRejectCode());
}
-bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const CTransaction& tx, bool fLimitFree,
+static bool IsCurrentForFeeEstimation()
+{
+ AssertLockHeld(cs_main);
+ if (IsInitialBlockDownload())
+ return false;
+ if (chainActive.Tip()->GetBlockTime() < (GetTime() - MAX_FEE_ESTIMATION_TIP_AGE))
+ return false;
+ if (chainActive.Height() < pindexBestHeader->nHeight - 1)
+ return false;
+ return true;
+}
+
+bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx, bool fLimitFree,
bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit, const CAmount& nAbsurdFee,
std::vector<uint256>& vHashTxnToUncache)
{
+ const CTransaction& tx = *ptx;
const uint256 hash = tx.GetHash();
AssertLockHeld(cs_main);
if (pfMissingInputs)
@@ -691,7 +704,8 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
}
}
- CTxMemPoolEntry entry(tx, nFees, nAcceptTime, dPriority, chainActive.Height(), pool.HasNoInputsOf(tx), inChainInputValue, fSpendsCoinbase, nSigOpsCost, lp);
+ CTxMemPoolEntry entry(ptx, nFees, nAcceptTime, dPriority, chainActive.Height(),
+ inChainInputValue, fSpendsCoinbase, nSigOpsCost, lp);
unsigned int nSize = entry.GetTxSize();
// Check that the transaction doesn't have an excessive number of
@@ -939,8 +953,13 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
}
pool.RemoveStaged(allConflicting, false);
+ // This transaction should only count for fee estimation if
+ // the node is not behind and it is not dependent on any other
+ // transactions in the mempool
+ bool validForFeeEstimation = IsCurrentForFeeEstimation() && pool.HasNoInputsOf(tx);
+
// Store transaction in memory
- pool.addUnchecked(hash, entry, setAncestors, !IsInitialBlockDownload());
+ pool.addUnchecked(hash, entry, setAncestors, validForFeeEstimation);
// trim mempool and check if tx was trimmed
if (!fOverrideMempoolLimit) {
@@ -955,7 +974,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
return true;
}
-bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
+bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree,
bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit, const CAmount nAbsurdFee)
{
std::vector<uint256> vHashTxToUncache;
@@ -970,7 +989,7 @@ bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const
return res;
}
-bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
+bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree,
bool* pfMissingInputs, bool fOverrideMempoolLimit, const CAmount nAbsurdFee)
{
return AcceptToMemoryPoolWithTime(pool, state, tx, fLimitFree, pfMissingInputs, GetTime(), fOverrideMempoolLimit, nAbsurdFee);
@@ -1498,7 +1517,7 @@ bool AbortNode(CValidationState& state, const std::string& strMessage, const std
* @param out The out point that corresponds to the tx input.
* @return True on success.
*/
-static bool ApplyTxInUndo(const CTxInUndo& undo, CCoinsViewCache& view, const COutPoint& out)
+bool ApplyTxInUndo(const CTxInUndo& undo, CCoinsViewCache& view, const COutPoint& out)
{
bool fClean = true;
@@ -1916,6 +1935,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
* or always and in all cases if we're in prune mode and are deleting files.
*/
bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) {
+ int64_t nMempoolUsage = mempool.DynamicMemoryUsage();
const CChainParams& chainparams = Params();
LOCK2(cs_main, cs_LastBlockFile);
static int64_t nLastWrite = 0;
@@ -1946,11 +1966,13 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) {
if (nLastSetChain == 0) {
nLastSetChain = nNow;
}
- size_t cacheSize = pcoinsTip->DynamicMemoryUsage();
- // The cache is large and close to the limit, but we have time now (not in the middle of a block processing).
- bool fCacheLarge = mode == FLUSH_STATE_PERIODIC && cacheSize * (10.0/9) > nCoinCacheUsage;
+ int64_t nMempoolSizeMax = GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
+ int64_t cacheSize = pcoinsTip->DynamicMemoryUsage();
+ int64_t nTotalSpace = nCoinCacheUsage + std::max<int64_t>(nMempoolSizeMax - nMempoolUsage, 0);
+ // The cache is large and we're within 10% and 100 MiB of the limit, but we have time now (not in the middle of a block processing).
+ bool fCacheLarge = mode == FLUSH_STATE_PERIODIC && cacheSize > std::max((9 * nTotalSpace) / 10, nTotalSpace - 100 * 1024 * 1024);
// The cache is over the limit, we have to write now.
- bool fCacheCritical = mode == FLUSH_STATE_IF_NEEDED && cacheSize > nCoinCacheUsage;
+ bool fCacheCritical = mode == FLUSH_STATE_IF_NEEDED && cacheSize > nTotalSpace;
// It's been a while since we wrote the block index to disk. Do this frequently, so we don't need to redownload after a crash.
bool fPeriodicWrite = mode == FLUSH_STATE_PERIODIC && nNow > nLastWrite + (int64_t)DATABASE_WRITE_INTERVAL * 1000000;
// It's been very long since we flushed the cache. Do this infrequently, to optimize cache usage.
@@ -2116,7 +2138,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara
const CTransaction& tx = *it;
// ignore validation errors in resurrected transactions
CValidationState stateDummy;
- if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL, true)) {
+ if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, it, false, NULL, true)) {
mempool.removeRecursive(tx);
} else if (mempool.exists(tx.GetHash())) {
vHashUpdate.push_back(tx.GetHash());
@@ -2202,7 +2224,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
int64_t nTime5 = GetTimeMicros(); nTimeChainState += nTime5 - nTime4;
LogPrint("bench", " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001);
// Remove conflicting transactions from the mempool.;
- mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight, !IsInitialBlockDownload());
+ mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight);
// Update chainActive & related variables.
UpdateTip(pindexNew, chainparams);
@@ -4054,15 +4076,16 @@ bool LoadMempool(void)
file >> num;
double prioritydummy = 0;
while (num--) {
+ CTransactionRef tx;
int64_t nTime;
int64_t nFeeDelta;
- CTransaction tx(deserialize, file);
+ file >> tx;
file >> nTime;
file >> nFeeDelta;
CAmount amountdelta = nFeeDelta;
if (amountdelta) {
- mempool.PrioritiseTransaction(tx.GetHash(), tx.GetHash().ToString(), prioritydummy, amountdelta);
+ mempool.PrioritiseTransaction(tx->GetHash(), tx->GetHash().ToString(), prioritydummy, amountdelta);
}
CValidationState state;
if (nTime + nExpiryTimeout > nNow) {