As reported in issue #6184, pruning doesn’t currently work well during initial block download if connected to a peer (like the relay client) which can deliver unrequested blocks at the tip before the node is synced. When that happens, blocks with a very large height are written to early block files, thus preventing pruning from taking place on those early files (due to the restriction against deleting block files containing blocks with a height greater than chainActive.Tip() - 288
).
#6221 attempts to deal with this better by allowing block files to at least not be contiguous, so that we can still prune later files even if an earlier one ends up containing a large-height block. However, even with that behavior change, during the several hours that initial download could take, it’s possible for dozens of block files to end up containing a block that is relatively recent, potentially causing the pruning target to be exceeded substantially for 2 days (~288 blocks) after starting up.
This pull goes further to improve behavior when connected to a peer that is serving unrequested blocks. The first commit tries to prevent block files from becoming too out-of-order by not processing an unrequested block if its height is more than 288 blocks past our tip.
- Regarding the choice of constant: there were two natural choices to consider, one was the constant used by pruning (288 == MIN_BLOCKS_TO_KEEP), the other is the BLOCK_DOWNLOAD_WINDOW (1024) which is used for a similar purpose when doing parallel fetching of blocks. The smaller MIN_BLOCKS_TO_KEEP value means that we’d be more likely to achieve our pruning target, and it seemed reasonable to me that we’d use it similarly for managing out-of-order-ness in block files to make pruning behave better. But I’m open to other suggestions for this value.
- While this change was motivated by pruning nodes, for simplicity’s sake I didn’t restrict this behavior change to pruning nodes.
The second commit changes the behavior when receiving unrequested blocks from whitelisted peers, so that those blocks are not automatically processed during initial block download. Instead, during IBD they are subject to the same conditions as when received from non-whitelisted peers.
- This change is to accommodate relay network users who whitelist the relay peer; without the second commit the first commit would have no effect. Alternatively, if it’s reasonable for users to not whitelist the relay peer, then perhaps we could drop this commit altogether.
- Before settling on using
IsInitialBlockDownload()
, I considered using the guard that prevents direct-fetching of inv’ed blocks, but that test was in my opinion worse:chainActive.Tip()->GetBlockTime() > GetAdjustedTime() - chainparams.GetConsensus().nPowTargetSpacing * 20
If this pull looks okay, I think it should be included in 0.11.