@ -627,7 +627,7 @@ void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins)
}
}
}
}
bool CTxMemPool : : accept ( CTransaction & tx , bool fCheckInputs ,
bool CTxMemPool : : accept ( CTransaction & tx , bool fCheckInputs , bool fLimitFree ,
bool * pfMissingInputs )
bool * pfMissingInputs )
{
{
if ( pfMissingInputs )
if ( pfMissingInputs )
@ -733,7 +733,7 @@ bool CTxMemPool::accept(CTransaction &tx, bool fCheckInputs,
// Don't accept it if it can't get into a block
// Don't accept it if it can't get into a block
int64 txMinFee = tx . GetMinFee ( 1000 , true , GMF_RELAY ) ;
int64 txMinFee = tx . GetMinFee ( 1000 , true , GMF_RELAY ) ;
if ( nFees < txMinFee )
if ( fLimitFree & & nFees < txMinFee )
return error ( " CTxMemPool::accept() : not enough fees %s, % " PRI64d " < % " PRI64d ,
return error ( " CTxMemPool::accept() : not enough fees %s, % " PRI64d " < % " PRI64d ,
hash . ToString ( ) . c_str ( ) ,
hash . ToString ( ) . c_str ( ) ,
nFees , txMinFee ) ;
nFees , txMinFee ) ;
@ -741,25 +741,24 @@ bool CTxMemPool::accept(CTransaction &tx, bool fCheckInputs,
// Continuously rate-limit free transactions
// Continuously rate-limit free transactions
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
// be annoying or make others' transactions take longer to confirm.
// be annoying or make others' transactions take longer to confirm.
if ( nFees < MIN_RELAY_TX_FEE )
if ( fLimitFree & & nFees < MIN_RELAY_TX_FEE )
{
{
static CCriticalSection cs ;
static double dFreeCount ;
static double dFreeCount ;
static int64 nLastTime ;
static int64 nLastTime ;
int64 nNow = GetTime ( ) ;
int64 nNow = GetTime ( ) ;
{
LOCK ( cs ) ;
// Use an exponentially decaying ~10-minute window:
dFreeCount * = pow ( 1.0 - 1.0 / 600.0 , ( double ) ( nNow - nLastTime ) ) ;
// Use an exponentially decaying ~10-minute window:
nLastTime = nNow ;
dFreeCount * = pow ( 1.0 - 1.0 / 600.0 , ( double ) ( nNow - nLastTime ) ) ;
// -limitfreerelay unit is thousand-bytes-per-minute
nLastTime = nNow ;
// At default rate it would take over a month to fill 1GB
// -limitfreerelay unit is thousand-bytes-per-minute
if ( dFreeCount > GetArg ( " -limitfreerelay " , 15 ) * 10 * 1000 & & ! IsFromMe ( tx ) )
// At default rate it would take over a month to fill 1GB
return error ( " CTxMemPool::accept() : free transaction rejected by rate limiter " ) ;
if ( dFreeCount > GetArg ( " -limitfreerelay " , 15 ) * 10 * 1000 )
if ( fDebug )
return error ( " CTxMemPool::accept() : free transaction rejected by rate limiter " ) ;
printf ( " Rate limit dFreeCount: %g => %g \n " , dFreeCount , dFreeCount + nSize ) ;
if ( fDebug )
dFreeCount + = nSize ;
printf ( " Rate limit dFreeCount: %g => %g \n " , dFreeCount , dFreeCount + nSize ) ;
}
dFreeCount + = nSize ;
}
}
// Check against previous transactions
// Check against previous transactions
@ -792,9 +791,9 @@ bool CTxMemPool::accept(CTransaction &tx, bool fCheckInputs,
return true ;
return true ;
}
}
bool CTransaction : : AcceptToMemoryPool ( bool fCheckInputs , bool * pfMissingInputs )
bool CTransaction : : AcceptToMemoryPool ( bool fCheckInputs , bool fLimitFree , bool * pfMissingInputs )
{
{
return mempool . accept ( * this , fCheckInputs , pfMissingInputs ) ;
return mempool . accept ( * this , fCheckInputs , fLimitFree , pfMissingInputs ) ;
}
}
bool CTxMemPool : : addUnchecked ( const uint256 & hash , CTransaction & tx )
bool CTxMemPool : : addUnchecked ( const uint256 & hash , CTransaction & tx )
@ -905,9 +904,9 @@ int CMerkleTx::GetBlocksToMaturity() const
}
}
bool CMerkleTx : : AcceptToMemoryPool ( bool fCheckInputs )
bool CMerkleTx : : AcceptToMemoryPool ( bool fCheckInputs , bool fLimitFree )
{
{
return CTransaction : : AcceptToMemoryPool ( fCheckInputs ) ;
return CTransaction : : AcceptToMemoryPool ( fCheckInputs , fLimitFree ) ;
}
}
@ -923,10 +922,10 @@ bool CWalletTx::AcceptWalletTransaction(bool fCheckInputs)
{
{
uint256 hash = tx . GetHash ( ) ;
uint256 hash = tx . GetHash ( ) ;
if ( ! mempool . exists ( hash ) & & pcoinsTip - > HaveCoins ( hash ) )
if ( ! mempool . exists ( hash ) & & pcoinsTip - > HaveCoins ( hash ) )
tx . AcceptToMemoryPool ( fCheckInputs ) ;
tx . AcceptToMemoryPool ( fCheckInputs , false ) ;
}
}
}
}
return AcceptToMemoryPool ( fCheckInputs ) ;
return AcceptToMemoryPool ( fCheckInputs , false ) ;
}
}
return false ;
return false ;
}
}
@ -1797,7 +1796,7 @@ bool SetBestChain(CBlockIndex* pindexNew)
// Resurrect memory transactions that were in the disconnected branch
// Resurrect memory transactions that were in the disconnected branch
BOOST_FOREACH ( CTransaction & tx , vResurrect )
BOOST_FOREACH ( CTransaction & tx , vResurrect )
tx . AcceptToMemoryPool ( ) ;
tx . AcceptToMemoryPool ( true , false ) ;
// Delete redundant memory transactions that are in the connected branch
// Delete redundant memory transactions that are in the connected branch
BOOST_FOREACH ( CTransaction & tx , vDelete ) {
BOOST_FOREACH ( CTransaction & tx , vDelete ) {
@ -3181,7 +3180,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom - > AddInventoryKnown ( inv ) ;
pfrom - > AddInventoryKnown ( inv ) ;
bool fMissingInputs = false ;
bool fMissingInputs = false ;
if ( tx . AcceptToMemoryPool ( true , & fMissingInputs ) )
if ( tx . AcceptToMemoryPool ( true , true , & fMissingInputs ) )
{
{
SyncWithWallets ( inv . hash , tx , NULL , true ) ;
SyncWithWallets ( inv . hash , tx , NULL , true ) ;
RelayMessage ( inv , vMsg ) ;
RelayMessage ( inv , vMsg ) ;
@ -3203,7 +3202,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
CInv inv ( MSG_TX , tx . GetHash ( ) ) ;
CInv inv ( MSG_TX , tx . GetHash ( ) ) ;
bool fMissingInputs2 = false ;
bool fMissingInputs2 = false ;
if ( tx . AcceptToMemoryPool ( true , & fMissingInputs2 ) )
if ( tx . AcceptToMemoryPool ( true , true , & fMissingInputs2 ) )
{
{
printf ( " accepted orphan tx %s \n " , inv . hash . ToString ( ) . substr ( 0 , 10 ) . c_str ( ) ) ;
printf ( " accepted orphan tx %s \n " , inv . hash . ToString ( ) . substr ( 0 , 10 ) . c_str ( ) ) ;
SyncWithWallets ( inv . hash , tx , NULL , true ) ;
SyncWithWallets ( inv . hash , tx , NULL , true ) ;
@ -3214,9 +3213,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
}
}
else if ( ! fMissingInputs2 )
else if ( ! fMissingInputs2 )
{
{
// invalid orphan
// invalid or too-little-fee or phan
vEraseQueue . push_back ( inv . hash ) ;
vEraseQueue . push_back ( inv . hash ) ;
printf ( " removed invalid orphan tx %s \n " , inv . hash . ToString ( ) . substr ( 0 , 10 ) . c_str ( ) ) ;
printf ( " removed orphan tx %s \n " , inv . hash . ToString ( ) . substr ( 0 , 10 ) . c_str ( ) ) ;
}
}
}
}
}
}