@ -789,6 +789,17 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
return true ;
return true ;
}
}
void LimitMempoolSize ( CTxMemPool & pool , size_t limit , unsigned long age ) {
int expired = pool . Expire ( GetTime ( ) - age ) ;
if ( expired ! = 0 )
LogPrint ( " mempool " , " Expired %i transactions from the memory pool \n " , expired ) ;
std : : vector < uint256 > vNoSpendsRemaining ;
pool . TrimToSize ( limit , & vNoSpendsRemaining ) ;
BOOST_FOREACH ( const uint256 & removed , vNoSpendsRemaining )
pcoinsTip - > Uncache ( removed ) ;
}
CAmount GetMinRelayFee ( const CTransaction & tx , const CTxMemPool & pool , unsigned int nBytes , bool fAllowFree )
CAmount GetMinRelayFee ( const CTransaction & tx , const CTxMemPool & pool , unsigned int nBytes , bool fAllowFree )
{
{
uint256 hash = tx . GetHash ( ) ;
uint256 hash = tx . GetHash ( ) ;
@ -824,8 +835,9 @@ std::string FormatStateMessage(const CValidationState &state)
state . GetRejectCode ( ) ) ;
state . GetRejectCode ( ) ) ;
}
}
bool AcceptToMemoryPool ( CTxMemPool & pool , CValidationState & state , const CTransaction & tx , bool fLimitFree ,
bool AcceptToMemoryPoolWorker ( CTxMemPool & pool , CValidationState & state , const CTransaction & tx , bool fLimitFree ,
bool * pfMissingInputs , bool fOverrideMempoolLimit , bool fRejectAbsurdFee )
bool * pfMissingInputs , bool fOverrideMempoolLimit , bool fRejectAbsurdFee ,
std : : vector < uint256 > & vHashTxnToUncache )
{
{
AssertLockHeld ( cs_main ) ;
AssertLockHeld ( cs_main ) ;
if ( pfMissingInputs )
if ( pfMissingInputs )
@ -906,13 +918,19 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
view . SetBackend ( viewMemPool ) ;
view . SetBackend ( viewMemPool ) ;
// do we already have it?
// do we already have it?
if ( view . HaveCoins ( hash ) )
bool fHadTxInCache = pcoinsTip - > HaveCoinsInCache ( hash ) ;
if ( view . HaveCoins ( hash ) ) {
if ( ! fHadTxInCache )
vHashTxnToUncache . push_back ( hash ) ;
return state . Invalid ( false , REJECT_ALREADY_KNOWN , " txn-already-known " ) ;
return state . Invalid ( false , REJECT_ALREADY_KNOWN , " txn-already-known " ) ;
}
// do all inputs exist?
// do all inputs exist?
// Note that this does not check for the presence of actual outputs (see the next check for that),
// Note that this does not check for the presence of actual outputs (see the next check for that),
// and only helps with filling in pfMissingInputs (to determine missing vs spent).
// and only helps with filling in pfMissingInputs (to determine missing vs spent).
BOOST_FOREACH ( const CTxIn txin , tx . vin ) {
BOOST_FOREACH ( const CTxIn txin , tx . vin ) {
if ( ! pcoinsTip - > HaveCoinsInCache ( txin . prevout . hash ) )
vHashTxnToUncache . push_back ( txin . prevout . hash ) ;
if ( ! view . HaveCoins ( txin . prevout . hash ) ) {
if ( ! view . HaveCoins ( txin . prevout . hash ) ) {
if ( pfMissingInputs )
if ( pfMissingInputs )
* pfMissingInputs = true ;
* pfMissingInputs = true ;
@ -1210,12 +1228,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// trim mempool and check if tx was trimmed
// trim mempool and check if tx was trimmed
if ( ! fOverrideMempoolLimit ) {
if ( ! fOverrideMempoolLimit ) {
int expired = pool . Expire ( GetTime ( ) - GetArg ( " -mempoolexpiry " , DEFAULT_MEMPOOL_EXPIRY ) * 60 * 60 ) ;
LimitMempoolSize ( pool , GetArg ( " -maxmempool " , DEFAULT_MAX_MEMPOOL_SIZE ) * 1000000 , GetArg ( " -mempoolexpiry " , DEFAULT_MEMPOOL_EXPIRY ) * 60 * 60 ) ;
if ( expired ! = 0 )
if ( ! pool . exists ( hash ) )
LogPrint ( " mempool " , " Expired %i transactions from the memory pool \n " , expired ) ;
pool . TrimToSize ( GetArg ( " -maxmempool " , DEFAULT_MAX_MEMPOOL_SIZE ) * 1000000 ) ;
if ( ! pool . exists ( tx . GetHash ( ) ) )
return state . DoS ( 0 , false , REJECT_INSUFFICIENTFEE , " mempool full " ) ;
return state . DoS ( 0 , false , REJECT_INSUFFICIENTFEE , " mempool full " ) ;
}
}
}
}
@ -1225,6 +1239,18 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
return true ;
return true ;
}
}
bool AcceptToMemoryPool ( CTxMemPool & pool , CValidationState & state , const CTransaction & tx , bool fLimitFree ,
bool * pfMissingInputs , bool fOverrideMempoolLimit , bool fRejectAbsurdFee )
{
std : : vector < uint256 > vHashTxToUncache ;
bool res = AcceptToMemoryPoolWorker ( pool , state , tx , fLimitFree , pfMissingInputs , fOverrideMempoolLimit , fRejectAbsurdFee , vHashTxToUncache ) ;
if ( ! res ) {
BOOST_FOREACH ( const uint256 & hashTx , vHashTxToUncache )
pcoinsTip - > Uncache ( hashTx ) ;
}
return res ;
}
/** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */
/** Return transaction in tx, 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 )
bool GetTransaction ( const uint256 & hash , CTransaction & txOut , const Consensus : : Params & consensusParams , uint256 & hashBlock , bool fAllowSlow )
{
{
@ -2571,7 +2597,7 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c
if ( fBlocksDisconnected ) {
if ( fBlocksDisconnected ) {
mempool . removeForReorg ( pcoinsTip , chainActive . Tip ( ) - > nHeight + 1 , STANDARD_LOCKTIME_VERIFY_FLAGS ) ;
mempool . removeForReorg ( pcoinsTip , chainActive . Tip ( ) - > nHeight + 1 , STANDARD_LOCKTIME_VERIFY_FLAGS ) ;
mempool . TrimToSize ( GetArg ( " -maxmempool " , DEFAULT_MAX_MEMPOOL_SIZE ) * 1000000 ) ;
LimitMempoolSize ( mempool , GetArg ( " -maxmempool " , DEFAULT_MAX_MEMPOOL_SIZE ) * 1000000 , GetArg ( " -mempoolexpiry " , DEFAULT_MEMPOOL_EXPIRY ) * 60 * 6 0 ) ;
}
}
mempool . check ( pcoinsTip ) ;
mempool . check ( pcoinsTip ) ;
@ -2686,7 +2712,7 @@ bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensus
}
}
}
}
mempool . TrimToSize ( GetArg ( " -maxmempool " , DEFAULT_MAX_MEMPOOL_SIZE ) * 1000000 ) ;
LimitMempoolSize ( mempool , GetArg ( " -maxmempool " , DEFAULT_MAX_MEMPOOL_SIZE ) * 1000000 , GetArg ( " -mempoolexpiry " , DEFAULT_MEMPOOL_EXPIRY ) * 60 * 6 0 ) ;
// The resulting new best tip may not be in setBlockIndexCandidates anymore, so
// The resulting new best tip may not be in setBlockIndexCandidates anymore, so
// add it again.
// add it again.
@ -4804,6 +4830,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if ( nDoS > 0 )
if ( nDoS > 0 )
Misbehaving ( pfrom - > GetId ( ) , nDoS ) ;
Misbehaving ( pfrom - > GetId ( ) , nDoS ) ;
}
}
FlushStateToDisk ( state , FLUSH_STATE_PERIODIC ) ;
}
}