Browse Source

orphaned tx makes no sense anymore

miguelfreitas
Miguel Freitas 12 years ago
parent
commit
943bff5921
  1. 6
      src/core.cpp
  2. 1
      src/core.h
  3. 138
      src/main.cpp

6
src/core.cpp

@ -78,6 +78,12 @@ uint256 CTransaction::GetHash() const
return SerializeHash(*this); return SerializeHash(*this);
} }
uint256 CTransaction::GetUsernameHash() const
{
return SerializeHash(userName);
}
std::string CTransaction::ToString() const std::string CTransaction::ToString() const
{ {
std::string str; std::string str;

1
src/core.h

@ -215,6 +215,7 @@ public:
} }
uint256 GetHash() const; uint256 GetHash() const;
uint256 GetUsernameHash() const;
bool IsSpamMessage() const bool IsSpamMessage() const
{ {

138
src/main.cpp

@ -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;

Loading…
Cancel
Save