@@ -486,7 +486,23 @@ func (bc *BlockChain) loadLastState() error {
486486 return bc .Reset ()
487487 }
488488 // Make sure the entire head block is available
489- currentBlock := bc .GetBlockByHash (head )
489+ currentHeader := bc .GetHeaderByHash (head )
490+ if currentHeader == nil {
491+ // Corrupt or empty database, init from scratch
492+ log .Warn ("Head header missing, resetting chain" , "hash" , head )
493+ return bc .Reset ()
494+ }
495+
496+ var currentBlock * types.Block
497+ if cmp := currentHeader .Number .Cmp (new (big.Int )); cmp == 1 {
498+ // Make sure the entire head block is available.
499+ currentBlock = bc .GetBlockByHash (head )
500+ } else if cmp == 0 {
501+ // On a pruned node the block body might not be available. But a pruned
502+ // block should never be the head block. The only exception is when, as
503+ // a last resort, chain is reset to genesis.
504+ currentBlock = bc .genesisBlock
505+ }
490506 if currentBlock == nil {
491507 // Corrupt or empty database, init from scratch
492508 log .Warn ("Head block missing, resetting chain" , "hash" , head )
@@ -497,7 +513,6 @@ func (bc *BlockChain) loadLastState() error {
497513 headBlockGauge .Update (int64 (currentBlock .NumberU64 ()))
498514
499515 // Restore the last known head header
500- currentHeader := currentBlock .Header ()
501516 if head := rawdb .ReadHeadHeaderHash (bc .db ); head != (common.Hash {}) {
502517 if header := bc .GetHeaderByHash (head ); header != nil {
503518 currentHeader = header
@@ -609,11 +624,13 @@ func (bc *BlockChain) SetHead(head uint64) error {
609624 }
610625 // Send chain head event to update the transaction pool
611626 if block := bc .CurrentBlock (); block == nil {
612- // This should never happen. In practice, previously currentBlock
613- // contained the entire block whereas now only a "marker", so there
614- // is an ever so slight chance for a race we should handle.
615- log .Error ("Current block not found in database" , "block" , block .Number (), "hash" , block .Hash ())
616- return fmt .Errorf ("current block missing: #%d [%x..]" , block .Number (), block .Hash ().Bytes ()[:4 ])
627+ if block .Number ().Uint64 () > 0 {
628+ // This should never happen. In practice, previously currentBlock
629+ // contained the entire block whereas now only a "marker", so there
630+ // is an ever so slight chance for a race we should handle.
631+ log .Error ("Current block not found in database" , "block" , block .Number (), "hash" , block .Hash ())
632+ return fmt .Errorf ("current block missing: #%d [%x..]" , block .Number (), block .Hash ().Bytes ()[:4 ])
633+ }
617634 } else {
618635 bc .chainHeadFeed .Send (ChainHeadEvent {Header : block .Header ()})
619636 }
@@ -630,11 +647,13 @@ func (bc *BlockChain) SetHeadWithTimestamp(timestamp uint64) error {
630647 }
631648 // Send chain head event to update the transaction pool
632649 if block := bc .CurrentBlock (); block == nil {
633- // This should never happen. In practice, previously currentBlock
634- // contained the entire block whereas now only a "marker", so there
635- // is an ever so slight chance for a race we should handle.
636- log .Error ("Current block not found in database" , "block" , block .Number (), "hash" , block .Hash ())
637- return fmt .Errorf ("current block missing: #%d [%x..]" , block .Number (), block .Hash ().Bytes ()[:4 ])
650+ if block .Number ().Uint64 () > 0 {
651+ // This should never happen. In practice, previously currentBlock
652+ // contained the entire block whereas now only a "marker", so there
653+ // is an ever so slight chance for a race we should handle.
654+ log .Error ("Current block not found in database" , "block" , block .Number (), "hash" , block .Hash ())
655+ return fmt .Errorf ("current block missing: #%d [%x..]" , block .Number (), block .Hash ().Bytes ()[:4 ])
656+ }
638657 } else {
639658 bc .chainHeadFeed .Send (ChainHeadEvent {Header : block .Header ()})
640659 }
0 commit comments