@@ -789,6 +789,17 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
789
789
return true ;
790
790
}
791
791
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
+
792
803
CAmount GetMinRelayFee (const CTransaction& tx, const CTxMemPool& pool, unsigned int nBytes, bool fAllowFree )
793
804
{
794
805
uint256 hash = tx.GetHash ();
@@ -824,8 +835,9 @@ std::string FormatStateMessage(const CValidationState &state)
824
835
state.GetRejectCode ());
825
836
}
826
837
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)
829
841
{
830
842
AssertLockHeld (cs_main);
831
843
if (pfMissingInputs)
@@ -906,13 +918,19 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
906
918
view.SetBackend (viewMemPool);
907
919
908
920
// 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);
910
925
return state.Invalid (false , REJECT_ALREADY_KNOWN, " txn-already-known" );
926
+ }
911
927
912
928
// do all inputs exist?
913
929
// Note that this does not check for the presence of actual outputs (see the next check for that),
914
930
// and only helps with filling in pfMissingInputs (to determine missing vs spent).
915
931
BOOST_FOREACH (const CTxIn txin, tx.vin ) {
932
+ if (!pcoinsTip->HaveCoinsInCache (txin.prevout .hash ))
933
+ vHashTxnToUncache.push_back (txin.prevout .hash );
916
934
if (!view.HaveCoins (txin.prevout .hash )) {
917
935
if (pfMissingInputs)
918
936
*pfMissingInputs = true ;
@@ -1210,12 +1228,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
1210
1228
1211
1229
// trim mempool and check if tx was trimmed
1212
1230
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))
1219
1233
return state.DoS (0 , false , REJECT_INSUFFICIENTFEE, " mempool full" );
1220
1234
}
1221
1235
}
@@ -1225,6 +1239,18 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
1225
1239
return true ;
1226
1240
}
1227
1241
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
+
1228
1254
/* * Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */
1229
1255
bool GetTransaction (const uint256 &hash, CTransaction &txOut, const Consensus::Params& consensusParams, uint256 &hashBlock, bool fAllowSlow )
1230
1256
{
@@ -2571,7 +2597,7 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c
2571
2597
2572
2598
if (fBlocksDisconnected ) {
2573
2599
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 );
2575
2601
}
2576
2602
mempool.check (pcoinsTip);
2577
2603
@@ -2686,7 +2712,7 @@ bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensus
2686
2712
}
2687
2713
}
2688
2714
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 );
2690
2716
2691
2717
// The resulting new best tip may not be in setBlockIndexCandidates anymore, so
2692
2718
// add it again.
@@ -4804,6 +4830,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
4804
4830
if (nDoS > 0 )
4805
4831
Misbehaving (pfrom->GetId (), nDoS);
4806
4832
}
4833
+ FlushStateToDisk (state, FLUSH_STATE_PERIODIC);
4807
4834
}
4808
4835
4809
4836
0 commit comments