@@ -337,17 +337,17 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
337337 if err := bc .loadLastState (); err != nil {
338338 return nil , err
339339 }
340- // Make sure the state associated with the block is available
340+ // Make sure the state associated with the block is available, or log out
341+ // if there is no available state, waiting for state sync.
341342 head := bc .CurrentBlock ()
342343 if ! bc .HasState (head .Root ) {
343344 if head .Number .Uint64 () == 0 {
344345 // The genesis state is missing, which is only possible in the path-based
345- // scheme. This situation occurs when the state syncer overwrites it.
346- //
347- // The solution is to reset the state to the genesis state. Although it may not
348- // match the sync target, the state healer will later address and correct any
349- // inconsistencies.
350- bc .resetState ()
346+ // scheme. This situation occurs when the initial state sync is not finished
347+ // yet, or the chain head is rewound below the pivot point. In both scenario,
348+ // there is no possible recovery approach except for rerunning a snap sync.
349+ // Do nothing here until the state syncer picks it up.
350+ log .Info ("Genesis state is missing, wait state sync" )
351351 } else {
352352 // Head state is missing, before the state recovery, find out the
353353 // disk layer point of snapshot(if it's enabled). Make sure the
@@ -630,28 +630,6 @@ func (bc *BlockChain) SetSafe(header *types.Header) {
630630 }
631631}
632632
633- // resetState resets the persistent state to genesis state if it's not present.
634- func (bc * BlockChain ) resetState () {
635- // Short circuit if the genesis state is already present.
636- root := bc .genesisBlock .Root ()
637- if bc .HasState (root ) {
638- return
639- }
640- // Reset the state database to empty for committing genesis state.
641- // Note, it should only happen in path-based scheme and Reset function
642- // is also only call-able in this mode.
643- if bc .triedb .Scheme () == rawdb .PathScheme {
644- if err := bc .triedb .Reset (types .EmptyRootHash ); err != nil {
645- log .Crit ("Failed to clean state" , "err" , err ) // Shouldn't happen
646- }
647- }
648- // Write genesis state into database.
649- if err := CommitGenesisState (bc .db , bc .triedb , bc .genesisBlock .Hash ()); err != nil {
650- log .Crit ("Failed to commit genesis state" , "err" , err )
651- }
652- log .Info ("Reset state to genesis" , "root" , root )
653- }
654-
655633// setHeadBeyondRoot rewinds the local chain to a new head with the extra condition
656634// that the rewind must pass the specified state root. This method is meant to be
657635// used when rewinding with snapshots enabled to ensure that we go back further than
@@ -687,7 +665,6 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
687665 if newHeadBlock == nil {
688666 log .Error ("Gap in the chain, rewinding to genesis" , "number" , header .Number , "hash" , header .Hash ())
689667 newHeadBlock = bc .genesisBlock
690- bc .resetState ()
691668 } else {
692669 // Block exists, keep rewinding until we find one with state,
693670 // keeping rewinding until we exceed the optional threshold
@@ -715,16 +692,14 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
715692 }
716693 }
717694 if beyondRoot || newHeadBlock .NumberU64 () == 0 {
718- if newHeadBlock .NumberU64 () == 0 {
719- bc .resetState ()
720- } else if ! bc .HasState (newHeadBlock .Root ()) {
695+ if ! bc .HasState (newHeadBlock .Root ()) && bc .stateRecoverable (newHeadBlock .Root ()) {
721696 // Rewind to a block with recoverable state. If the state is
722697 // missing, run the state recovery here.
723698 if err := bc .triedb .Recover (newHeadBlock .Root ()); err != nil {
724699 log .Crit ("Failed to rollback state" , "err" , err ) // Shouldn't happen
725700 }
701+ log .Debug ("Rewound to block with state" , "number" , newHeadBlock .NumberU64 (), "hash" , newHeadBlock .Hash ())
726702 }
727- log .Debug ("Rewound to block with state" , "number" , newHeadBlock .NumberU64 (), "hash" , newHeadBlock .Hash ())
728703 break
729704 }
730705 log .Debug ("Skipping block with threshold state" , "number" , newHeadBlock .NumberU64 (), "hash" , newHeadBlock .Hash (), "root" , newHeadBlock .Root ())
@@ -739,6 +714,15 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
739714 // to low, so it's safe to update in-memory markers directly.
740715 bc .currentBlock .Store (newHeadBlock .Header ())
741716 headBlockGauge .Update (int64 (newHeadBlock .NumberU64 ()))
717+
718+ // The head state is missing, which is only possible in the path-based
719+ // scheme. This situation occurs when the chain head is rewound below
720+ // the pivot point. In this scenario, there is no possible recovery
721+ // approach except for rerunning a snap sync. Do nothing here until the
722+ // state syncer picks it up.
723+ if ! bc .HasState (newHeadBlock .Root ()) {
724+ log .Info ("Chain is stateless, wait state sync" , "number" , newHeadBlock .Number (), "hash" , newHeadBlock .Hash ())
725+ }
742726 }
743727 // Rewind the snap block in a simpleton way to the target head
744728 if currentSnapBlock := bc .CurrentSnapBlock (); currentSnapBlock != nil && header .Number .Uint64 () < currentSnapBlock .Number .Uint64 () {
@@ -838,7 +822,7 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error {
838822 // Reset the trie database with the fresh snap synced state.
839823 root := block .Root ()
840824 if bc .triedb .Scheme () == rawdb .PathScheme {
841- if err := bc .triedb .Reset (root ); err != nil {
825+ if err := bc .triedb .Enable (root ); err != nil {
842826 return err
843827 }
844828 }
0 commit comments