@@ -789,6 +789,17 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
789789 return true ;
790790}
791791
792+ void LimitMempoolSize (CTxMemPool& pool, size_t limit, unsigned long age) {
793+ int expired = pool.Expire (GetTime () - age);
794+ if (expired != 0 )
795+ LogPrint (" mempool" , " Expired %i transactions from the memory pool\n " , expired);
796+
797+ std::vector<uint256> vNoSpendsRemaining;
798+ pool.TrimToSize (limit, &vNoSpendsRemaining);
799+ BOOST_FOREACH (const uint256& removed, vNoSpendsRemaining)
800+ pcoinsTip->Uncache (removed);
801+ }
802+
792803CAmount GetMinRelayFee (const CTransaction& tx, const CTxMemPool& pool, unsigned int nBytes, bool fAllowFree )
793804{
794805 uint256 hash = tx.GetHash ();
@@ -824,8 +835,9 @@ std::string FormatStateMessage(const CValidationState &state)
824835 state.GetRejectCode ());
825836}
826837
827- bool AcceptToMemoryPool (CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree ,
828- bool * pfMissingInputs, bool fOverrideMempoolLimit , bool fRejectAbsurdFee )
838+ bool AcceptToMemoryPoolWorker (CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree ,
839+ bool * pfMissingInputs, bool fOverrideMempoolLimit , bool fRejectAbsurdFee ,
840+ std::vector<uint256>& vHashTxnToUncache)
829841{
830842 AssertLockHeld (cs_main);
831843 if (pfMissingInputs)
@@ -906,13 +918,19 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
906918 view.SetBackend (viewMemPool);
907919
908920 // do we already have it?
909- if (view.HaveCoins (hash))
921+ bool fHadTxInCache = pcoinsTip->HaveCoinsInCache (hash);
922+ if (view.HaveCoins (hash)) {
923+ if (!fHadTxInCache )
924+ vHashTxnToUncache.push_back (hash);
910925 return state.Invalid (false , REJECT_ALREADY_KNOWN, " txn-already-known" );
926+ }
911927
912928 // do all inputs exist?
913929 // Note that this does not check for the presence of actual outputs (see the next check for that),
914930 // and only helps with filling in pfMissingInputs (to determine missing vs spent).
915931 BOOST_FOREACH (const CTxIn txin, tx.vin ) {
932+ if (!pcoinsTip->HaveCoinsInCache (txin.prevout .hash ))
933+ vHashTxnToUncache.push_back (txin.prevout .hash );
916934 if (!view.HaveCoins (txin.prevout .hash )) {
917935 if (pfMissingInputs)
918936 *pfMissingInputs = true ;
@@ -1210,12 +1228,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
12101228
12111229 // trim mempool and check if tx was trimmed
12121230 if (!fOverrideMempoolLimit ) {
1213- int expired = pool.Expire (GetTime () - GetArg (" -mempoolexpiry" , DEFAULT_MEMPOOL_EXPIRY) * 60 * 60 );
1214- if (expired != 0 )
1215- LogPrint (" mempool" , " Expired %i transactions from the memory pool\n " , expired);
1216-
1217- pool.TrimToSize (GetArg (" -maxmempool" , DEFAULT_MAX_MEMPOOL_SIZE) * 1000000 );
1218- if (!pool.exists (tx.GetHash ()))
1231+ LimitMempoolSize (pool, GetArg (" -maxmempool" , DEFAULT_MAX_MEMPOOL_SIZE) * 1000000 , GetArg (" -mempoolexpiry" , DEFAULT_MEMPOOL_EXPIRY) * 60 * 60 );
1232+ if (!pool.exists (hash))
12191233 return state.DoS (0 , false , REJECT_INSUFFICIENTFEE, " mempool full" );
12201234 }
12211235 }
@@ -1225,6 +1239,18 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
12251239 return true ;
12261240}
12271241
1242+ bool AcceptToMemoryPool (CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree ,
1243+ bool * pfMissingInputs, bool fOverrideMempoolLimit , bool fRejectAbsurdFee )
1244+ {
1245+ std::vector<uint256> vHashTxToUncache;
1246+ bool res = AcceptToMemoryPoolWorker (pool, state, tx, fLimitFree , pfMissingInputs, fOverrideMempoolLimit , fRejectAbsurdFee , vHashTxToUncache);
1247+ if (!res) {
1248+ BOOST_FOREACH (const uint256& hashTx, vHashTxToUncache)
1249+ pcoinsTip->Uncache (hashTx);
1250+ }
1251+ return res;
1252+ }
1253+
12281254/* * Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */
12291255bool GetTransaction (const uint256 &hash, CTransaction &txOut, const Consensus::Params& consensusParams, uint256 &hashBlock, bool fAllowSlow )
12301256{
@@ -2571,7 +2597,7 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c
25712597
25722598 if (fBlocksDisconnected ) {
25732599 mempool.removeForReorg (pcoinsTip, chainActive.Tip ()->nHeight + 1 , STANDARD_LOCKTIME_VERIFY_FLAGS);
2574- mempool. TrimToSize ( GetArg (" -maxmempool" , DEFAULT_MAX_MEMPOOL_SIZE) * 1000000 );
2600+ LimitMempoolSize (mempool, GetArg (" -maxmempool" , DEFAULT_MAX_MEMPOOL_SIZE) * 1000000 , GetArg ( " -mempoolexpiry " , DEFAULT_MEMPOOL_EXPIRY) * 60 * 60 );
25752601 }
25762602 mempool.check (pcoinsTip);
25772603
@@ -2686,7 +2712,7 @@ bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensus
26862712 }
26872713 }
26882714
2689- mempool. TrimToSize ( GetArg (" -maxmempool" , DEFAULT_MAX_MEMPOOL_SIZE) * 1000000 );
2715+ LimitMempoolSize (mempool, GetArg (" -maxmempool" , DEFAULT_MAX_MEMPOOL_SIZE) * 1000000 , GetArg ( " -mempoolexpiry " , DEFAULT_MEMPOOL_EXPIRY) * 60 * 60 );
26902716
26912717 // The resulting new best tip may not be in setBlockIndexCandidates anymore, so
26922718 // add it again.
@@ -4804,6 +4830,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
48044830 if (nDoS > 0 )
48054831 Misbehaving (pfrom->GetId (), nDoS);
48064832 }
4833+ FlushStateToDisk (state, FLUSH_STATE_PERIODIC);
48074834 }
48084835
48094836
0 commit comments