@@ -514,19 +514,33 @@ func (bc *BlockChain) loadLastState() error {
514
514
log .Warn ("Empty database, resetting chain" )
515
515
return bc .Reset ()
516
516
}
517
- // Make sure the entire head block is available
518
- headBlock := bc .GetBlockByHash (head )
517
+ headHeader := bc .GetHeaderByHash (head )
518
+ if headHeader == nil {
519
+ // Corrupt or empty database, init from scratch
520
+ log .Warn ("Head header missing, resetting chain" , "hash" , head )
521
+ return bc .Reset ()
522
+ }
523
+
524
+ var headBlock * types.Block
525
+ if cmp := headHeader .Number .Cmp (new (big.Int )); cmp == 1 {
526
+ // Make sure the entire head block is available.
527
+ headBlock = bc .GetBlockByHash (head )
528
+ } else if cmp == 0 {
529
+ // On a pruned node the block body might not be available. But a pruned
530
+ // block should never be the head block. The only exception is when, as
531
+ // a last resort, chain is reset to genesis.
532
+ headBlock = bc .genesisBlock
533
+ }
519
534
if headBlock == nil {
520
535
// Corrupt or empty database, init from scratch
521
536
log .Warn ("Head block missing, resetting chain" , "hash" , head )
522
537
return bc .Reset ()
523
538
}
524
539
// Everything seems to be fine, set as the head block
525
- bc .currentBlock .Store (headBlock . Header () )
540
+ bc .currentBlock .Store (headHeader )
526
541
headBlockGauge .Update (int64 (headBlock .NumberU64 ()))
527
542
528
543
// Restore the last known head header
529
- headHeader := headBlock .Header ()
530
544
if head := rawdb .ReadHeadHeaderHash (bc .db ); head != (common.Hash {}) {
531
545
if header := bc .GetHeaderByHash (head ); header != nil {
532
546
headHeader = header
@@ -642,11 +656,15 @@ func (bc *BlockChain) SetHead(head uint64) error {
642
656
// Send chain head event to update the transaction pool
643
657
header := bc .CurrentBlock ()
644
658
if block := bc .GetBlock (header .Hash (), header .Number .Uint64 ()); block == nil {
645
- // This should never happen. In practice, previously currentBlock
646
- // contained the entire block whereas now only a "marker", so there
647
- // is an ever so slight chance for a race we should handle.
648
- log .Error ("Current block not found in database" , "block" , header .Number , "hash" , header .Hash ())
649
- return fmt .Errorf ("current block missing: #%d [%x..]" , header .Number , header .Hash ().Bytes ()[:4 ])
659
+ // In a pruned node the genesis block will not exist in the freezer.
660
+ // It should not happen that we set head to any other pruned block.
661
+ if header .Number .Uint64 () > 0 {
662
+ // This should never happen. In practice, previously currentBlock
663
+ // contained the entire block whereas now only a "marker", so there
664
+ // is an ever so slight chance for a race we should handle.
665
+ log .Error ("Current block not found in database" , "block" , header .Number , "hash" , header .Hash ())
666
+ return fmt .Errorf ("current block missing: #%d [%x..]" , header .Number , header .Hash ().Bytes ()[:4 ])
667
+ }
650
668
}
651
669
bc .chainHeadFeed .Send (ChainHeadEvent {Header : header })
652
670
return nil
@@ -663,11 +681,15 @@ func (bc *BlockChain) SetHeadWithTimestamp(timestamp uint64) error {
663
681
// Send chain head event to update the transaction pool
664
682
header := bc .CurrentBlock ()
665
683
if block := bc .GetBlock (header .Hash (), header .Number .Uint64 ()); block == nil {
666
- // This should never happen. In practice, previously currentBlock
667
- // contained the entire block whereas now only a "marker", so there
668
- // is an ever so slight chance for a race we should handle.
669
- log .Error ("Current block not found in database" , "block" , header .Number , "hash" , header .Hash ())
670
- return fmt .Errorf ("current block missing: #%d [%x..]" , header .Number , header .Hash ().Bytes ()[:4 ])
684
+ // In a pruned node the genesis block will not exist in the freezer.
685
+ // It should not happen that we set head to any other pruned block.
686
+ if header .Number .Uint64 () > 0 {
687
+ // This should never happen. In practice, previously currentBlock
688
+ // contained the entire block whereas now only a "marker", so there
689
+ // is an ever so slight chance for a race we should handle.
690
+ log .Error ("Current block not found in database" , "block" , header .Number , "hash" , header .Hash ())
691
+ return fmt .Errorf ("current block missing: #%d [%x..]" , header .Number , header .Hash ().Bytes ()[:4 ])
692
+ }
671
693
}
672
694
bc .chainHeadFeed .Send (ChainHeadEvent {Header : header })
673
695
return nil
0 commit comments