@@ -202,6 +202,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
202202 // Create the idle freezer instance
203203 frdb , err := newChainFreezer (resolveChainFreezerDir (ancient ), namespace , readonly )
204204 if err != nil {
205+ printChainMetadata (db )
205206 return nil , err
206207 }
207208 // Since the freezer can be stored separately from the user's key-value database,
@@ -233,17 +234,30 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
233234 // the freezer and the key-value store.
234235 frgenesis , err := frdb .Ancient (ChainFreezerHashTable , 0 )
235236 if err != nil {
237+ printChainMetadata (db )
236238 return nil , fmt .Errorf ("failed to retrieve genesis from ancient %v" , err )
237239 } else if ! bytes .Equal (kvgenesis , frgenesis ) {
240+ printChainMetadata (db )
238241 return nil , fmt .Errorf ("genesis mismatch: %#x (leveldb) != %#x (ancients)" , kvgenesis , frgenesis )
239242 }
240243 // Key-value store and freezer belong to the same network. Ensure that they
241244 // are contiguous, otherwise we might end up with a non-functional freezer.
242245 if kvhash , _ := db .Get (headerHashKey (frozen )); len (kvhash ) == 0 {
243246 // Subsequent header after the freezer limit is missing from the database.
244247 // Reject startup if the database has a more recent head.
245- if ldbNum := * ReadHeaderNumber (db , ReadHeadHeaderHash (db )); ldbNum > frozen - 1 {
246- return nil , fmt .Errorf ("gap in the chain between ancients (#%d) and leveldb (#%d) " , frozen , ldbNum )
248+ if head := * ReadHeaderNumber (db , ReadHeadHeaderHash (db )); head > frozen - 1 {
249+ // Find the smallest block stored in the key-value store
250+ // in range of [frozen, head]
251+ var number uint64
252+ for number = frozen ; number <= head ; number ++ {
253+ if present , _ := db .Has (headerHashKey (number )); present {
254+ break
255+ }
256+ }
257+ // We are about to exit on error. Print database metdata beore exiting
258+ printChainMetadata (db )
259+ return nil , fmt .Errorf ("gap in the chain between ancients [0 - #%d] and leveldb [#%d - #%d] " ,
260+ frozen - 1 , number , head )
247261 }
248262 // Database contains only older data than the freezer, this happens if the
249263 // state was wiped and reinited from an existing freezer.
@@ -260,6 +274,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
260274 // Key-value store contains more data than the genesis block, make sure we
261275 // didn't freeze anything yet.
262276 if kvblob , _ := db .Get (headerHashKey (1 )); len (kvblob ) == 0 {
277+ printChainMetadata (db )
263278 return nil , errors .New ("ancient chain segments already extracted, please set --datadir.ancient to the correct path" )
264279 }
265280 // Block #1 is still in the database, we're allowed to init a new freezer
@@ -581,3 +596,42 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
581596 }
582597 return nil
583598}
599+
600+ // printChainMetadata prints out chain metadata to stderr.
601+ func printChainMetadata (db ethdb.KeyValueStore ) {
602+ fmt .Fprintf (os .Stderr , "Chain metadata\n " )
603+ for _ , v := range ReadChainMetadata (db ) {
604+ fmt .Fprintf (os .Stderr , " %s\n " , strings .Join (v , ": " ))
605+ }
606+ fmt .Fprintf (os .Stderr , "\n \n " )
607+ }
608+
609+ // ReadChainMetadata returns a set of key/value pairs that contains informatin
610+ // about the database chain status. This can be used for diagnostic purposes
611+ // when investigating the state of the node.
612+ func ReadChainMetadata (db ethdb.KeyValueStore ) [][]string {
613+ pp := func (val * uint64 ) string {
614+ if val == nil {
615+ return "<nil>"
616+ }
617+ return fmt .Sprintf ("%d (%#x)" , * val , * val )
618+ }
619+ data := [][]string {
620+ {"databaseVersion" , pp (ReadDatabaseVersion (db ))},
621+ {"headBlockHash" , fmt .Sprintf ("%v" , ReadHeadBlockHash (db ))},
622+ {"headFastBlockHash" , fmt .Sprintf ("%v" , ReadHeadFastBlockHash (db ))},
623+ {"headHeaderHash" , fmt .Sprintf ("%v" , ReadHeadHeaderHash (db ))},
624+ {"lastPivotNumber" , pp (ReadLastPivotNumber (db ))},
625+ {"len(snapshotSyncStatus)" , fmt .Sprintf ("%d bytes" , len (ReadSnapshotSyncStatus (db )))},
626+ {"snapshotDisabled" , fmt .Sprintf ("%v" , ReadSnapshotDisabled (db ))},
627+ {"snapshotJournal" , fmt .Sprintf ("%d bytes" , len (ReadSnapshotJournal (db )))},
628+ {"snapshotRecoveryNumber" , pp (ReadSnapshotRecoveryNumber (db ))},
629+ {"snapshotRoot" , fmt .Sprintf ("%v" , ReadSnapshotRoot (db ))},
630+ {"txIndexTail" , pp (ReadTxIndexTail (db ))},
631+ {"fastTxLookupLimit" , pp (ReadFastTxLookupLimit (db ))},
632+ }
633+ if b := ReadSkeletonSyncStatus (db ); b != nil {
634+ data = append (data , []string {"SkeletonSyncStatus" , string (b )})
635+ }
636+ return data
637+ }
0 commit comments