Skip to content

Commit 266921e

Browse files
committed
Merge pull request #3516 from sipa/serorphans-head
Store orphan blocks in serialized form
2 parents b1347d5 + da0fecf commit 266921e

File tree

1 file changed

+41
-17
lines changed

1 file changed

+41
-17
lines changed

src/main.cpp

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,13 @@ int64_t CTransaction::nMinRelayTxFee = 10000;
5656

5757
static CMedianFilter<int> cPeerBlockCounts(8, 0); // Amount of blocks that other nodes claim to have
5858

59-
map<uint256, CBlock*> mapOrphanBlocks;
60-
multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
59+
struct COrphanBlock {
60+
uint256 hashBlock;
61+
uint256 hashPrev;
62+
vector<unsigned char> vchBlock;
63+
};
64+
map<uint256, COrphanBlock*> mapOrphanBlocks;
65+
multimap<uint256, COrphanBlock*> mapOrphanBlocksByPrev;
6166

6267
map<uint256, CTransaction> mapOrphanTransactions;
6368
map<uint256, set<uint256> > mapOrphanTransactionsByPrev;
@@ -985,12 +990,19 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex)
985990
return true;
986991
}
987992

988-
uint256 static GetOrphanRoot(const CBlockHeader* pblock)
993+
uint256 static GetOrphanRoot(const uint256& hash)
989994
{
995+
map<uint256, COrphanBlock*>::iterator it = mapOrphanBlocks.find(hash);
996+
if (it == mapOrphanBlocks.end())
997+
return hash;
998+
990999
// Work back to the first block in the orphan chain
991-
while (mapOrphanBlocks.count(pblock->hashPrevBlock))
992-
pblock = mapOrphanBlocks[pblock->hashPrevBlock];
993-
return pblock->GetHash();
1000+
do {
1001+
map<uint256, COrphanBlock*>::iterator it2 = mapOrphanBlocks.find(it->second->hashPrev);
1002+
if (it2 == mapOrphanBlocks.end())
1003+
return it->first;
1004+
it = it2;
1005+
} while(true);
9941006
}
9951007

9961008
int64_t GetBlockValue(int nHeight, int64_t nFees)
@@ -2277,12 +2289,19 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
22772289

22782290
// Accept orphans as long as there is a node to request its parents from
22792291
if (pfrom) {
2280-
CBlock* pblock2 = new CBlock(*pblock);
2292+
COrphanBlock* pblock2 = new COrphanBlock();
2293+
{
2294+
CDataStream ss(SER_DISK, CLIENT_VERSION);
2295+
ss << *pblock;
2296+
pblock2->vchBlock = std::vector<unsigned char>(ss.begin(), ss.end());
2297+
}
2298+
pblock2->hashBlock = hash;
2299+
pblock2->hashPrev = pblock->hashPrevBlock;
22812300
mapOrphanBlocks.insert(make_pair(hash, pblock2));
2282-
mapOrphanBlocksByPrev.insert(make_pair(pblock2->hashPrevBlock, pblock2));
2301+
mapOrphanBlocksByPrev.insert(make_pair(pblock2->hashPrev, pblock2));
22832302

22842303
// Ask this guy to fill in what we're missing
2285-
PushGetBlocks(pfrom, chainActive.Tip(), GetOrphanRoot(pblock2));
2304+
PushGetBlocks(pfrom, chainActive.Tip(), GetOrphanRoot(hash));
22862305
}
22872306
return true;
22882307
}
@@ -2297,17 +2316,22 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
22972316
for (unsigned int i = 0; i < vWorkQueue.size(); i++)
22982317
{
22992318
uint256 hashPrev = vWorkQueue[i];
2300-
for (multimap<uint256, CBlock*>::iterator mi = mapOrphanBlocksByPrev.lower_bound(hashPrev);
2319+
for (multimap<uint256, COrphanBlock*>::iterator mi = mapOrphanBlocksByPrev.lower_bound(hashPrev);
23012320
mi != mapOrphanBlocksByPrev.upper_bound(hashPrev);
23022321
++mi)
23032322
{
2304-
CBlock* pblockOrphan = (*mi).second;
2323+
CBlock block;
2324+
{
2325+
CDataStream ss(mi->second->vchBlock, SER_DISK, CLIENT_VERSION);
2326+
ss >> block;
2327+
}
2328+
block.BuildMerkleTree();
23052329
// Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan resolution (that is, feeding people an invalid block based on LegitBlockX in order to get anyone relaying LegitBlockX banned)
23062330
CValidationState stateDummy;
2307-
if (AcceptBlock(*pblockOrphan, stateDummy))
2308-
vWorkQueue.push_back(pblockOrphan->GetHash());
2309-
mapOrphanBlocks.erase(pblockOrphan->GetHash());
2310-
delete pblockOrphan;
2331+
if (AcceptBlock(block, stateDummy))
2332+
vWorkQueue.push_back(mi->second->hashBlock);
2333+
mapOrphanBlocks.erase(mi->second->hashBlock);
2334+
delete mi->second;
23112335
}
23122336
mapOrphanBlocksByPrev.erase(hashPrev);
23132337
}
@@ -3331,7 +3355,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
33313355
if (!fImporting && !fReindex)
33323356
pfrom->AskFor(inv);
33333357
} else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) {
3334-
PushGetBlocks(pfrom, chainActive.Tip(), GetOrphanRoot(mapOrphanBlocks[inv.hash]));
3358+
PushGetBlocks(pfrom, chainActive.Tip(), GetOrphanRoot(inv.hash));
33353359
} else if (nInv == nLastBlock) {
33363360
// In case we are on a very long side-chain, it is possible that we already have
33373361
// the last block in an inv bundle sent in response to getblocks. Try to detect
@@ -4119,7 +4143,7 @@ class CMainCleanup
41194143
mapBlockIndex.clear();
41204144

41214145
// orphan blocks
4122-
std::map<uint256, CBlock*>::iterator it2 = mapOrphanBlocks.begin();
4146+
std::map<uint256, COrphanBlock*>::iterator it2 = mapOrphanBlocks.begin();
41234147
for (; it2 != mapOrphanBlocks.end(); it2++)
41244148
delete (*it2).second;
41254149
mapOrphanBlocks.clear();

0 commit comments

Comments
 (0)