diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index 1cbf031975..0b2017eac4 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -406,7 +406,7 @@ func inspectTrie(ctx *cli.Context) error { var err error blockNumber, err = strconv.ParseUint(ctx.Args().Get(0), 10, 64) if err != nil { - return fmt.Errorf("failed to Parse blocknum, Args[0]: %v, err: %v", ctx.Args().Get(0), err) + return fmt.Errorf("failed to parse blocknum, Args[0]: %v, err: %v", ctx.Args().Get(0), err) } } @@ -417,26 +417,26 @@ func inspectTrie(ctx *cli.Context) error { var err error jobnum, err = strconv.ParseUint(ctx.Args().Get(1), 10, 64) if err != nil { - return fmt.Errorf("failed to Parse jobnum, Args[1]: %v, err: %v", ctx.Args().Get(1), err) + return fmt.Errorf("failed to parse jobnum, Args[1]: %v, err: %v", ctx.Args().Get(1), err) } topN = 10 } else { var err error jobnum, err = strconv.ParseUint(ctx.Args().Get(1), 10, 64) if err != nil { - return fmt.Errorf("failed to Parse jobnum, Args[1]: %v, err: %v", ctx.Args().Get(1), err) + return fmt.Errorf("failed to parse jobnum, Args[1]: %v, err: %v", ctx.Args().Get(1), err) } topN, err = strconv.ParseUint(ctx.Args().Get(2), 10, 64) if err != nil { - return fmt.Errorf("failed to Parse topn, Args[1]: %v, err: %v", ctx.Args().Get(1), err) + return fmt.Errorf("failed to parse topn, Args[1]: %v, err: %v", ctx.Args().Get(1), err) } } if blockNumber != math.MaxUint64 { headerBlockHash = rawdb.ReadCanonicalHash(db, blockNumber) if headerBlockHash == (common.Hash{}) { - return errors.New("ReadHeadBlockHash empry hash") + return errors.New("ReadHeadBlockHash empty hash") } blockHeader := rawdb.ReadHeader(db, headerBlockHash, blockNumber) trieRootHash = blockHeader.Root @@ -508,7 +508,7 @@ func ancientInspect(ctx *cli.Context) error { stack, _ := makeConfigNode(ctx) defer stack.Close() - db := utils.MakeChainDatabase(ctx, stack, true, true) + db := utils.MakeChainDatabase(ctx, stack, true, false) defer db.Close() return rawdb.AncientInspect(db) } diff --git a/core/rawdb/database.go b/core/rawdb/database.go index 29c70e6961..0f7fb77a5c 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -61,7 +61,7 @@ func (frdb *freezerdb) BlockStoreReader() ethdb.Reader { } func (frdb *freezerdb) BlockStoreWriter() ethdb.Writer { - //TODO implement me + // TODO implement me panic("implement me") } @@ -188,7 +188,7 @@ func (db *nofreezedb) Ancients() (uint64, error) { return 0, errNotSupported } -// Ancients returns an error as we don't have a backing chain freezer. +// ItemAmountInAncient returns an error as we don't have a backing chain freezer. func (db *nofreezedb) ItemAmountInAncient() (uint64, error) { return 0, errNotSupported } @@ -326,6 +326,112 @@ func NewDatabase(db ethdb.KeyValueStore) ethdb.Database { return &nofreezedb{KeyValueStore: db} } +type emptyfreezedb struct { + ethdb.KeyValueStore + diffStore ethdb.KeyValueStore + stateStore ethdb.Database + blockStore ethdb.Database +} + +// HasAncient returns nil for pruned db that we don't have a backing chain freezer. +func (db *emptyfreezedb) HasAncient(kind string, number uint64) (bool, error) { + return false, nil +} + +// Ancient returns nil for pruned db that we don't have a backing chain freezer. +func (db *emptyfreezedb) Ancient(kind string, number uint64) ([]byte, error) { + return nil, nil +} + +// AncientRange returns nil for pruned db that we don't have a backing chain freezer. +func (db *emptyfreezedb) AncientRange(kind string, start, max, maxByteSize uint64) ([][]byte, error) { + return nil, nil +} + +// Ancients returns nil for pruned db that we don't have a backing chain freezer. +func (db *emptyfreezedb) Ancients() (uint64, error) { + return 0, nil +} + +// ItemAmountInAncient returns nil for pruned db that we don't have a backing chain freezer. +func (db *emptyfreezedb) ItemAmountInAncient() (uint64, error) { + return 0, nil +} + +// Tail returns nil for pruned db that we don't have a backing chain freezer. +func (db *emptyfreezedb) Tail() (uint64, error) { + return 0, nil +} + +// AncientSize returns nil for pruned db that we don't have a backing chain freezer. +func (db *emptyfreezedb) AncientSize(kind string) (uint64, error) { + return 0, nil +} + +// ModifyAncients returns nil for pruned db that we don't have a backing chain freezer. +func (db *emptyfreezedb) ModifyAncients(func(ethdb.AncientWriteOp) error) (int64, error) { + return 0, nil +} + +// TruncateHead returns nil for pruned db that we don't have a backing chain freezer. +func (db *emptyfreezedb) TruncateHead(items uint64) (uint64, error) { + return 0, nil +} + +// TruncateTail returns nil for pruned db that we don't have a backing chain freezer. +func (db *emptyfreezedb) TruncateTail(items uint64) (uint64, error) { + return 0, nil +} + +// TruncateTableTail returns nil for pruned db that we don't have a backing chain freezer. +func (db *emptyfreezedb) TruncateTableTail(kind string, tail uint64) (uint64, error) { + return 0, nil +} + +// ResetTable returns nil for pruned db that we don't have a backing chain freezer. +func (db *emptyfreezedb) ResetTable(kind string, startAt uint64, onlyEmpty bool) error { + return nil +} + +// Sync returns nil for pruned db that we don't have a backing chain freezer. +func (db *emptyfreezedb) Sync() error { + return nil +} + +func (db *emptyfreezedb) DiffStore() ethdb.KeyValueStore { return db } +func (db *emptyfreezedb) SetDiffStore(diff ethdb.KeyValueStore) {} +func (db *emptyfreezedb) StateStore() ethdb.Database { return db } +func (db *emptyfreezedb) SetStateStore(state ethdb.Database) {} +func (db *emptyfreezedb) StateStoreReader() ethdb.Reader { return db } +func (db *emptyfreezedb) BlockStore() ethdb.Database { return db } +func (db *emptyfreezedb) SetBlockStore(block ethdb.Database) {} +func (db *emptyfreezedb) BlockStoreReader() ethdb.Reader { return db } +func (db *emptyfreezedb) BlockStoreWriter() ethdb.Writer { return db } +func (db *emptyfreezedb) ReadAncients(fn func(reader ethdb.AncientReaderOp) error) (err error) { + return nil +} +func (db *emptyfreezedb) AncientOffSet() uint64 { return 0 } + +// MigrateTable returns nil for pruned db that we don't have a backing chain freezer. +func (db *emptyfreezedb) MigrateTable(kind string, convert convertLegacyFn) error { + return nil +} + +// AncientDatadir returns nil for pruned db that we don't have a backing chain freezer. +func (db *emptyfreezedb) AncientDatadir() (string, error) { + return "", nil +} +func (db *emptyfreezedb) SetupFreezerEnv(env *ethdb.FreezerEnv) error { + return nil +} + +// NewEmptyFreezeDB is used for CLI such as `geth db inspect` in pruned db that we don't +// have a backing chain freezer. +// WARNING: it must be only used in the above case. +func NewEmptyFreezeDB(db ethdb.KeyValueStore) ethdb.Database { + return &emptyfreezedb{KeyValueStore: db} +} + // NewFreezerDb only create a freezer without statedb. func NewFreezerDb(db ethdb.KeyValueStore, frz, namespace string, readonly bool, newOffSet uint64) (*Freezer, error) { // Create the idle freezer instance, this operation should be atomic to avoid mismatch between offset and acientDB. @@ -375,6 +481,12 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st offset = ReadOffSetOfCurrentAncientFreezer(db) } + // This case is used for someone who wants to execute geth db inspect CLI in a pruned db + if !disableFreeze && readonly && ReadAncientType(db) == PruneFreezerType { + log.Warn("Disk db is pruned, return an empty freezer db which is used for CLI") + return NewEmptyFreezeDB(db), nil + } + if pruneAncientData && !disableFreeze && !readonly { frdb, err := newPrunedFreezer(resolveChainFreezerDir(ancient), db, offset) if err != nil { @@ -627,7 +739,7 @@ func Open(o OpenOptions) (ethdb.Database, error) { } if ReadAncientType(kvdb) == PruneFreezerType { if !o.PruneAncientData { - log.Warn("Disk db is pruned") + log.Warn("NOTICE: You're opening a pruned disk db!") } } if len(o.AncientsDirectory) == 0 {