@ -162,6 +162,29 @@ namespace {
@@ -162,6 +162,29 @@ namespace {
*/
map < uint256 , NodeId > mapBlockSource ;
/**
* Filter for transactions that were recently rejected by
* AcceptToMemoryPool . These are not rerequested until the chain tip
* changes , at which point the entire filter is reset . Protected by
* cs_main .
*
* Without this filter we ' d be re - requesting txs from each of our peers ,
* increasing bandwidth consumption considerably . For instance , with 100
* peers , half of which relay a tx we don ' t accept , that might be a 50 x
* bandwidth increase . A flooding attacker attempting to roll - over the
* filter using minimum - sized , 60 byte , transactions might manage to send
* 1000 / sec if we have fast peers , so we pick 120 , 000 to give our peers a
* two minute window to send invs to us .
*
* Decreasing the false positive rate is fairly cheap , so we pick one in a
* million to make it highly unlikely for users to have issues with this
* filter .
*
* Memory used : 1.7 MB
*/
boost : : scoped_ptr < CRollingBloomFilter > recentRejects ;
uint256 hashRecentRejectsChainTip ;
/** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */
struct QueuedBlock {
uint256 hash ;
@ -3267,6 +3290,7 @@ void UnloadBlockIndex()
@@ -3267,6 +3290,7 @@ void UnloadBlockIndex()
setDirtyBlockIndex . clear ( ) ;
setDirtyFileInfo . clear ( ) ;
mapNodeState . clear ( ) ;
recentRejects . reset ( NULL ) ;
BOOST_FOREACH ( BlockMap : : value_type & entry , mapBlockIndex ) {
delete entry . second ;
@ -3320,6 +3344,9 @@ bool InitBlockIndex() {
@@ -3320,6 +3344,9 @@ bool InitBlockIndex() {
}
}
// Initialize global variables that cannot be constructed at startup.
recentRejects . reset ( new CRollingBloomFilter ( 120000 , 0.000001 ) ) ;
return true ;
}
@ -3689,9 +3716,19 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
@@ -3689,9 +3716,19 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
case MSG_TX :
{
bool txInMap = false ;
txInMap = mempool . exists ( inv . hash ) ;
return txInMap | | mapOrphanTransactions . count ( inv . hash ) | |
if ( chainActive . Tip ( ) - > GetBlockHash ( ) ! = hashRecentRejectsChainTip )
{
// If the chain tip has changed previously rejected transactions
// might be now valid, e.g. due to a nLockTime'd tx becoming valid,
// or a double-spend. Reset the rejects filter and give those
// txs a second chance.
hashRecentRejectsChainTip = chainActive . Tip ( ) - > GetBlockHash ( ) ;
recentRejects - > reset ( ) ;
}
return recentRejects - > contains ( inv . hash ) | |
mempool . exists ( inv . hash ) | |
mapOrphanTransactions . count ( inv . hash ) | |
pcoinsTip - > HaveCoins ( inv . hash ) ;
}
case MSG_BLOCK :
@ -4292,6 +4329,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -4292,6 +4329,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Probably non-standard or insufficient fee/priority
LogPrint ( " mempool " , " removed orphan tx %s \n " , orphanHash . ToString ( ) ) ;
vEraseQueue . push_back ( orphanHash ) ;
recentRejects - > insert ( orphanHash ) ;
}
mempool . check ( pcoinsTip ) ;
}
@ -4309,12 +4347,24 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -4309,12 +4347,24 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
unsigned int nEvicted = LimitOrphanTxSize ( nMaxOrphanTx ) ;
if ( nEvicted > 0 )
LogPrint ( " mempool " , " mapOrphan overflow, removed %u tx \n " , nEvicted ) ;
} else if ( pfrom - > fWhitelisted ) {
} else {
// AcceptToMemoryPool() returned false, possibly because the tx is
// already in the mempool; if the tx isn't in the mempool that
// means it was rejected and we shouldn't ask for it again.
if ( ! mempool . exists ( tx . GetHash ( ) ) ) {
recentRejects - > insert ( tx . GetHash ( ) ) ;
}
if ( pfrom - > fWhitelisted ) {
// Always relay transactions received from whitelisted peers, even
// if they are already in the mempool (allowing the node to function
// as a gateway for nodes hidden behind it).
// if they were rejected from the mempool, allowing the node to
// function as a gateway for nodes hidden behind it.
//
// FIXME: This includes invalid transactions, which means a
// whitelisted peer could get us banned! We may want to change
// that.
RelayTransaction ( tx ) ;
}
}
int nDoS = 0 ;
if ( state . IsInvalid ( nDoS ) )
{