diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2014-01-11 17:28:34 +0100 |
---|---|---|
committer | Pieter Wuille <sipa@ulyssis.org> | 2014-01-31 14:16:06 +0100 |
commit | bbde1e99c893924dbef135f42c14f4df9828c6e5 (patch) | |
tree | 6f944d405b502bb3c4bc9616704e5fe72494b888 /src/main.cpp | |
parent | 15ec451554b5889a92651b9fe71bf01047ba9fc3 (diff) |
Limit the number of orphan blocks
In case the total number of orphan blocks in memory exceeds a limit
(currently set to 750), a random orphan block (which is not
depended on by another orphan block) is dropped. This means it will
need to be downloaded again, but it won't consume memory until then.
Diffstat (limited to 'src/main.cpp')
-rw-r--r-- | src/main.cpp | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/src/main.cpp b/src/main.cpp index 4532b776c6..d33ad2fa95 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1054,6 +1054,31 @@ uint256 static GetOrphanRoot(const uint256& hash) } while(true); } +// Remove a random orphan block (which does not have any dependent orphans). +void static PruneOrphanBlocks() +{ + if (mapOrphanBlocksByPrev.size() <= MAX_ORPHAN_BLOCKS) + return; + + // Pick a random orphan block. + int pos = insecure_rand() % mapOrphanBlocksByPrev.size(); + std::multimap<uint256, COrphanBlock*>::iterator it = mapOrphanBlocksByPrev.begin(); + while (pos--) it++; + + // As long as this block has other orphans depending on it, move to one of those successors. + do { + std::multimap<uint256, COrphanBlock*>::iterator it2 = mapOrphanBlocksByPrev.find(it->second->hashBlock); + if (it2 == mapOrphanBlocksByPrev.end()) + break; + it = it2; + } while(1); + + uint256 hash = it->second->hashBlock; + delete it->second; + mapOrphanBlocksByPrev.erase(it); + mapOrphanBlocks.erase(hash); +} + int64_t GetBlockValue(int nHeight, int64_t nFees) { int64_t nSubsidy = 50 * COIN; @@ -2373,10 +2398,11 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl // If we don't already have its previous block, shunt it off to holding area until we get it if (pblock->hashPrevBlock != 0 && !mapBlockIndex.count(pblock->hashPrevBlock)) { - LogPrintf("ProcessBlock: ORPHAN BLOCK, prev=%s\n", pblock->hashPrevBlock.ToString()); + LogPrintf("ProcessBlock: ORPHAN BLOCK %lu, prev=%s\n", (unsigned long)mapOrphanBlocks.size(), pblock->hashPrevBlock.ToString()); // Accept orphans as long as there is a node to request its parents from if (pfrom) { + PruneOrphanBlocks(); COrphanBlock* pblock2 = new COrphanBlock(); { CDataStream ss(SER_DISK, CLIENT_VERSION); |