@@ -202,6 +202,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
202
202
// Create the idle freezer instance
203
203
frdb , err := newChainFreezer (resolveChainFreezerDir (ancient ), namespace , readonly )
204
204
if err != nil {
205
+ printChainMetadata (db )
205
206
return nil , err
206
207
}
207
208
// 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
233
234
// the freezer and the key-value store.
234
235
frgenesis , err := frdb .Ancient (ChainFreezerHashTable , 0 )
235
236
if err != nil {
237
+ printChainMetadata (db )
236
238
return nil , fmt .Errorf ("failed to retrieve genesis from ancient %v" , err )
237
239
} else if ! bytes .Equal (kvgenesis , frgenesis ) {
240
+ printChainMetadata (db )
238
241
return nil , fmt .Errorf ("genesis mismatch: %#x (leveldb) != %#x (ancients)" , kvgenesis , frgenesis )
239
242
}
240
243
// Key-value store and freezer belong to the same network. Ensure that they
241
244
// are contiguous, otherwise we might end up with a non-functional freezer.
242
245
if kvhash , _ := db .Get (headerHashKey (frozen )); len (kvhash ) == 0 {
243
246
// Subsequent header after the freezer limit is missing from the database.
244
247
// 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 )
247
261
}
248
262
// Database contains only older data than the freezer, this happens if the
249
263
// state was wiped and reinited from an existing freezer.
@@ -260,6 +274,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
260
274
// Key-value store contains more data than the genesis block, make sure we
261
275
// didn't freeze anything yet.
262
276
if kvblob , _ := db .Get (headerHashKey (1 )); len (kvblob ) == 0 {
277
+ printChainMetadata (db )
263
278
return nil , errors .New ("ancient chain segments already extracted, please set --datadir.ancient to the correct path" )
264
279
}
265
280
// 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 {
581
596
}
582
597
return nil
583
598
}
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