Skip to content

Commit

Permalink
Limit the number of orphan blocks
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sipa committed Jan 31, 2014
1 parent 15ec451 commit bbde1e9
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 1 deletion.
28 changes: 27 additions & 1 deletion src/main.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions src/main.h
Expand Up @@ -45,6 +45,8 @@ static const unsigned int MAX_STANDARD_TX_SIZE = 100000;
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
/** The maximum number of orphan transactions kept in memory */
static const unsigned int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100;
/** The maximum number of orphan blocks kept in memory */
static const unsigned int MAX_ORPHAN_BLOCKS = 750;
/** The maximum size of a blk?????.dat file (since 0.8) */
static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB
/** The pre-allocation chunk size for blk?????.dat files (since 0.8) */
Expand Down

0 comments on commit bbde1e9

Please sign in to comment.