diff --git a/accept.go b/accept.go index 65ac2819..98674eec 100644 --- a/accept.go +++ b/accept.go @@ -91,6 +91,22 @@ func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, fastAdd bool) error return RuleError(str) } + // Find the latest known good checkpoint and prevent blocks which fork + // the main chain before it. This prevents storage of new, otherwise + // valid, blocks which build off of old blocks that are likely at a + // much easier difficulty and therefore could be used to waste cache and + // disk space. + checkpointBlock, err := b.findLatestKnownCheckpoint() + if err != nil { + return err + } + if checkpointBlock != nil && blockHeight < checkpointBlock.Height() { + str := fmt.Sprintf("block at height %d forks the main chain "+ + "before the previous checkpoint at height %d", + blockHeight, checkpointBlock.Height()) + return RuleError(str) + } + if !fastAdd { // Reject version 1 blocks once a majority of the network has // upgraded. diff --git a/process.go b/process.go index 42d08181..281a36c0 100644 --- a/process.go +++ b/process.go @@ -119,10 +119,10 @@ func (b *BlockChain) ProcessBlock(block *btcutil.Block, fastAdd bool) error { // Find the latest known checkpoint and perform some additional checks // based on the checkpoint. This provides a few nice properties such as - // preventing forks from blocks before the last checkpoint, rejecting - // easy to mine, but otherwise bogus, blocks that could be used to eat - // memory, and ensuring expected (versus claimed) proof of work - // requirements since the last checkpoint are met. + // preventing old side chain blocks before the last checkpoint, + // rejecting easy to mine, but otherwise bogus, blocks that could be + // used to eat memory, and ensuring expected (versus claimed) proof of + // work requirements since the last checkpoint are met. blockHeader := &block.MsgBlock().Header checkpointBlock, err := b.findLatestKnownCheckpoint() if err != nil {