diff --git a/core/blockchain.go b/core/blockchain.go index 025107cc52..e352b9cc6d 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -764,21 +764,10 @@ func (bc *BlockChain) initializeHistoryPruning(latest uint64) error { log.Error("Database pruned beyond configured history mode", "tail", freezerTail, "target", target, "mode", policy.Mode) return fmt.Errorf("database pruned beyond requested history (tail=%d, target=%d)", freezerTail, target) } - // Need to prune (freezerTail < target). - switch policy.Mode { - case history.KeepPostMerge, history.KeepPostPrague: - // Static modes require the user to run 'geth prune-history' offline - // rather than blocking startup for hours (tx index pruning is slow). - return fmt.Errorf("history not pruned to target block %d (current tail %d), run 'geth prune-history --history.chain=%s' first", target, freezerTail, policy.Mode) - - case history.KeepRecent: - // The rolling pruner will gradually catch up in the background. - if freezerTail > 0 { - bc.updateHistoryPrunePoint(freezerTail) - } - log.Warn("Chain history is behind pruning target, rolling pruner will catch up", "tail", freezerTail, "target", target) - } - return nil + // Need to prune (freezerTail < target). Large-scale pruning is not + // performed at startup to avoid blocking the node for hours (tx index + // pruning is particularly slow). Use 'geth prune-history' instead. + return fmt.Errorf("history not pruned to target block %d (current tail %d), run 'geth prune-history' first", target, freezerTail) } // SetHead rewinds the local chain to a new head. Depending on whether the node diff --git a/core/history_pruner_test.go b/core/history_pruner_test.go index c9bfd3bbd7..7aacecd8bc 100644 --- a/core/history_pruner_test.go +++ b/core/history_pruner_test.go @@ -182,19 +182,20 @@ func TestInitHistoryPruningStaticModeRequiresPruneHistory(t *testing.T) { } } -func TestInitHistoryPruningKeepRecentAllowsStartup(t *testing.T) { - db, gspec, _ := newTestChain(t, 200) +func TestInitHistoryPruningKeepRecentRequiresPruneHistory(t *testing.T) { + db, gspec, blocks := newTestChain(t, 200) defer db.Close() - // Reopen with KeepRecent and a small window. The tail (0) is behind the - // target but KeepRecent should still allow startup — the rolling pruner - // handles catch-up in the background. + // Set the head block so CurrentBlock() returns block 200 on reopen. + rawdb.WriteHeadBlockHash(db, blocks[len(blocks)-1].Hash()) + + // Reopen with KeepRecent and a small window. The tail (0) is behind + // the target (200-50=150), so startup should fail. policy := history.HistoryPolicy{Mode: history.KeepRecent, Window: 50} - chain, err := reopenChain(db, gspec, policy) - if err != nil { - t.Fatalf("unexpected error: %v", err) + _, err := reopenChain(db, gspec, policy) + if err == nil { + t.Fatal("expected error when history not pruned to target, got nil") } - defer chain.Stop() } func TestInitHistoryPruningStaticModeBeyondTarget(t *testing.T) {