@ -54,9 +54,6 @@ CMedianFilter<int> cPeerBlockCounts(8, 0); // Amount of blocks that other nodes
map < uint256 , CBlock * > mapOrphanBlocks ;
map < uint256 , CBlock * > mapOrphanBlocks ;
multimap < uint256 , CBlock * > mapOrphanBlocksByPrev ;
multimap < uint256 , CBlock * > mapOrphanBlocksByPrev ;
map < uint256 , CDataStream * > mapOrphanTransactions ;
map < uint256 , map < uint256 , CDataStream * > > mapOrphanTransactionsByPrev ;
// Constant stuff for coinbase transactions we create:
// Constant stuff for coinbase transactions we create:
CScript COINBASE_FLAGS ;
CScript COINBASE_FLAGS ;
@ -389,84 +386,6 @@ bool CCoinsViewMemPool::HaveCoins(const uint256 &txid) {
CCoinsViewCache * pcoinsTip = NULL ;
CCoinsViewCache * pcoinsTip = NULL ;
CBlockTreeDB * pblocktree = NULL ;
CBlockTreeDB * pblocktree = NULL ;
//////////////////////////////////////////////////////////////////////////////
//
// mapOrphanTransactions
//
bool AddOrphanTx ( const CDataStream & vMsg )
{
CTransaction tx ;
CDataStream ( vMsg ) > > tx ;
uint256 hash = tx . GetHash ( ) ;
if ( mapOrphanTransactions . count ( hash ) )
return false ;
CDataStream * pvMsg = new CDataStream ( vMsg ) ;
// Ignore big transactions, to avoid a
// send-big-orphans memory exhaustion attack. If a peer has a legitimate
// large transaction with a missing parent then we assume
// it will rebroadcast it later, after the parent transaction(s)
// have been mined or received.
// 10,000 orphans, each of which is at most 5,000 bytes big is
// at most 500 megabytes of orphans:
if ( pvMsg - > size ( ) > 5000 )
{
printf ( " ignoring large orphan tx (size: % " PRIszu " , hash: %s) \n " , pvMsg - > size ( ) , hash . ToString ( ) . c_str ( ) ) ;
delete pvMsg ;
return false ;
}
mapOrphanTransactions [ hash ] = pvMsg ;
/* [MF]
BOOST_FOREACH ( const CTxIn & txin , tx . vin )
mapOrphanTransactionsByPrev [ txin . prevout . hash ] . insert ( make_pair ( hash , pvMsg ) ) ;
*/
printf ( " stored orphan tx %s (mapsz % " PRIszu " ) \n " , hash . ToString ( ) . c_str ( ) ,
mapOrphanTransactions . size ( ) ) ;
return true ;
}
void static EraseOrphanTx ( uint256 hash )
{
if ( ! mapOrphanTransactions . count ( hash ) )
return ;
const CDataStream * pvMsg = mapOrphanTransactions [ hash ] ;
CTransaction tx ;
CDataStream ( * pvMsg ) > > tx ;
/* [MF]
BOOST_FOREACH ( const CTxIn & txin , tx . vin )
{
mapOrphanTransactionsByPrev [ txin . prevout . hash ] . erase ( hash ) ;
if ( mapOrphanTransactionsByPrev [ txin . prevout . hash ] . empty ( ) )
mapOrphanTransactionsByPrev . erase ( txin . prevout . hash ) ;
}
*/
delete pvMsg ;
mapOrphanTransactions . erase ( hash ) ;
}
unsigned int LimitOrphanTxSize ( unsigned int nMaxOrphans )
{
unsigned int nEvicted = 0 ;
while ( mapOrphanTransactions . size ( ) > nMaxOrphans )
{
// Evict a random orphan:
uint256 randomhash = GetRandHash ( ) ;
map < uint256 , CDataStream * > : : iterator it = mapOrphanTransactions . lower_bound ( randomhash ) ;
if ( it = = mapOrphanTransactions . end ( ) )
it = mapOrphanTransactions . begin ( ) ;
EraseOrphanTx ( it - > first ) ;
+ + nEvicted ;
}
return nEvicted ;
}
bool IsStandardTx ( const CTransaction & tx , string & reason )
bool IsStandardTx ( const CTransaction & tx , string & reason )
@ -2785,7 +2704,7 @@ bool static AlreadyHave(const CInv& inv)
LOCK ( mempool . cs ) ;
LOCK ( mempool . cs ) ;
txInMap = mempool . exists ( inv . hash ) ;
txInMap = mempool . exists ( inv . hash ) ;
}
}
return txInMap | | mapOrphanTransactions . count ( inv . hash ) | |
return txInMap | |
pcoinsTip - > HaveCoins ( inv . hash ) ;
pcoinsTip - > HaveCoins ( inv . hash ) ;
}
}
case MSG_BLOCK :
case MSG_BLOCK :
@ -3248,8 +3167,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
else if ( strCommand = = " tx " )
else if ( strCommand = = " tx " )
{
{
vector < uint256 > vWorkQueue ;
vector < uint256 > vEraseQueue ;
CDataStream vMsg ( vRecv ) ;
CDataStream vMsg ( vRecv ) ;
CTransaction tx ;
CTransaction tx ;
vRecv > > tx ;
vRecv > > tx ;
@ -3273,53 +3190,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
{
RelayTransaction ( tx , inv . hash , vMsg ) ;
RelayTransaction ( tx , inv . hash , vMsg ) ;
mapAlreadyAskedFor . erase ( inv ) ;
mapAlreadyAskedFor . erase ( inv ) ;
vWorkQueue . push_back ( inv . hash ) ;
vEraseQueue . push_back ( inv . hash ) ;
// Recursively process any orphan transactions that depended on this one
for ( unsigned int i = 0 ; i < vWorkQueue . size ( ) ; i + + )
{
uint256 hashPrev = vWorkQueue [ i ] ;
for ( map < uint256 , CDataStream * > : : iterator mi = mapOrphanTransactionsByPrev [ hashPrev ] . begin ( ) ;
mi ! = mapOrphanTransactionsByPrev [ hashPrev ] . end ( ) ;
+ + mi )
{
const CDataStream & vMsg = * ( ( * mi ) . second ) ;
CTransaction tx ;
CDataStream ( vMsg ) > > tx ;
CInv inv ( MSG_TX , tx . GetHash ( ) ) ;
bool fMissingInputs2 = false ;
// Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan resolution (that is, feeding people an invalid transaction based on LegitTxX in order to get anyone relaying LegitTxX banned)
CValidationState stateDummy ;
if ( mempool . accept ( stateDummy , tx , true , & fMissingInputs2 ) )
{
printf ( " accepted orphan tx %s \n " , inv . hash . ToString ( ) . c_str ( ) ) ;
RelayTransaction ( tx , inv . hash , vMsg ) ;
mapAlreadyAskedFor . erase ( inv ) ;
vWorkQueue . push_back ( inv . hash ) ;
vEraseQueue . push_back ( inv . hash ) ;
}
else if ( ! fMissingInputs2 )
{
// invalid or too-little-fee orphan
vEraseQueue . push_back ( inv . hash ) ;
printf ( " removed orphan tx %s \n " , inv . hash . ToString ( ) . c_str ( ) ) ;
}
}
}
BOOST_FOREACH ( uint256 hash , vEraseQueue )
EraseOrphanTx ( hash ) ;
}
else if ( fMissingInputs )
{
AddOrphanTx ( vMsg ) ;
// DoS prevention: do not allow mapOrphanTransactions to grow unbounded
unsigned int nEvicted = LimitOrphanTxSize ( MAX_ORPHAN_TRANSACTIONS ) ;
if ( nEvicted > 0 )
printf ( " mapOrphan overflow, removed %u tx \n " , nEvicted ) ;
}
}
int nDoS ;
int nDoS ;
if ( state . IsInvalid ( nDoS ) )
if ( state . IsInvalid ( nDoS ) )
@ -4315,11 +4185,5 @@ public:
for ( ; it2 ! = mapOrphanBlocks . end ( ) ; it2 + + )
for ( ; it2 ! = mapOrphanBlocks . end ( ) ; it2 + + )
delete ( * it2 ) . second ;
delete ( * it2 ) . second ;
mapOrphanBlocks . clear ( ) ;
mapOrphanBlocks . clear ( ) ;
// orphan transactions
std : : map < uint256 , CDataStream * > : : iterator it3 = mapOrphanTransactions . begin ( ) ;
for ( ; it3 ! = mapOrphanTransactions . end ( ) ; it3 + + )
delete ( * it3 ) . second ;
mapOrphanTransactions . clear ( ) ;
}
}
} instance_of_cmaincleanup ;
} instance_of_cmaincleanup ;