aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2014-01-11 17:28:34 +0100
committerPieter Wuille <sipa@ulyssis.org>2014-01-31 14:16:06 +0100
commitbbde1e99c893924dbef135f42c14f4df9828c6e5 (patch)
tree6f944d405b502bb3c4bc9616704e5fe72494b888 /src/main.cpp
parent15ec451554b5889a92651b9fe71bf01047ba9fc3 (diff)
downloadbitcoin-bbde1e99c893924dbef135f42c14f4df9828c6e5.tar.xz
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.cpp28
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);