@@ -337,17 +337,17 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
337
337
if err := bc .loadLastState (); err != nil {
338
338
return nil , err
339
339
}
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.
341
342
head := bc .CurrentBlock ()
342
343
if ! bc .HasState (head .Root ) {
343
344
if head .Number .Uint64 () == 0 {
344
345
// 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" )
351
351
} else {
352
352
// Head state is missing, before the state recovery, find out the
353
353
// disk layer point of snapshot(if it's enabled). Make sure the
@@ -630,28 +630,6 @@ func (bc *BlockChain) SetSafe(header *types.Header) {
630
630
}
631
631
}
632
632
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
-
655
633
// setHeadBeyondRoot rewinds the local chain to a new head with the extra condition
656
634
// that the rewind must pass the specified state root. This method is meant to be
657
635
// 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
687
665
if newHeadBlock == nil {
688
666
log .Error ("Gap in the chain, rewinding to genesis" , "number" , header .Number , "hash" , header .Hash ())
689
667
newHeadBlock = bc .genesisBlock
690
- bc .resetState ()
691
668
} else {
692
669
// Block exists, keep rewinding until we find one with state,
693
670
// keeping rewinding until we exceed the optional threshold
@@ -715,16 +692,14 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
715
692
}
716
693
}
717
694
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 ()) {
721
696
// Rewind to a block with recoverable state. If the state is
722
697
// missing, run the state recovery here.
723
698
if err := bc .triedb .Recover (newHeadBlock .Root ()); err != nil {
724
699
log .Crit ("Failed to rollback state" , "err" , err ) // Shouldn't happen
725
700
}
701
+ log .Debug ("Rewound to block with state" , "number" , newHeadBlock .NumberU64 (), "hash" , newHeadBlock .Hash ())
726
702
}
727
- log .Debug ("Rewound to block with state" , "number" , newHeadBlock .NumberU64 (), "hash" , newHeadBlock .Hash ())
728
703
break
729
704
}
730
705
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
739
714
// to low, so it's safe to update in-memory markers directly.
740
715
bc .currentBlock .Store (newHeadBlock .Header ())
741
716
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
+ }
742
726
}
743
727
// Rewind the snap block in a simpleton way to the target head
744
728
if currentSnapBlock := bc .CurrentSnapBlock (); currentSnapBlock != nil && header .Number .Uint64 () < currentSnapBlock .Number .Uint64 () {
@@ -838,7 +822,7 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error {
838
822
// Reset the trie database with the fresh snap synced state.
839
823
root := block .Root ()
840
824
if bc .triedb .Scheme () == rawdb .PathScheme {
841
- if err := bc .triedb .Reset (root ); err != nil {
825
+ if err := bc .triedb .Enable (root ); err != nil {
842
826
return err
843
827
}
844
828
}
0 commit comments