@@ -591,17 +591,45 @@ func (hc *HeaderChain) setHead(headBlock uint64, headTime uint64, updateFn Updat
591591 hashes = append (hashes , hdr .Hash ())
592592 }
593593 for _ , hash := range hashes {
594+ // Remove the associated block body and receipts if required.
595+ //
596+ // If the block is in the chain freezer, then this delete operation
597+ // is actually ineffective.
594598 if delFn != nil {
595599 delFn (batch , hash , num )
596600 }
601+ // Remove the hash->number mapping along with the header itself
597602 rawdb .DeleteHeader (batch , hash , num )
598603 }
604+ // Remove the number->hash mapping
599605 rawdb .DeleteCanonicalHash (batch , num )
600606 }
601607 }
602608 // Flush all accumulated deletions.
603609 if err := batch .Write (); err != nil {
604- log .Crit ("Failed to rewind block" , "error" , err )
610+ log .Crit ("Failed to commit batch in setHead" , "err" , err )
611+ }
612+ // Explicitly flush the pending writes in the key-value store to disk, ensuring
613+ // data durability of the previous deletions.
614+ if err := hc .chainDb .Sync (); err != nil {
615+ log .Crit ("Failed to sync the key-value store in setHead" , "err" , err )
616+ }
617+ // Truncate the excessive chain segments in the ancient store.
618+ // These are actually deferred deletions from the loop above.
619+ //
620+ // This step must be performed after synchronizing the key-value store;
621+ // otherwise, in the event of a panic, it's theoretically possible to
622+ // lose recent key-value store writes while the ancient store deletions
623+ // remain, leading to data inconsistency.
624+ if delFn != nil {
625+ // Ignore the error here since light client won't hit this path
626+ frozen , _ := hc .chainDb .Ancients ()
627+ if headBlock + 1 < frozen {
628+ _ , err := hc .chainDb .TruncateHead (headBlock + 1 )
629+ if err != nil {
630+ log .Crit ("Failed to truncate head block" , "err" , err )
631+ }
632+ }
605633 }
606634 // Clear out any stale content from the caches
607635 hc .headerCache .Purge ()
0 commit comments