From a44dc7912f96d44798683823574b06189e417acb Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Wed, 6 Mar 2024 12:06:00 +0800 Subject: [PATCH] refactor: support statestore reader --- cmd/geth/chaincmd.go | 2 +- cmd/geth/dbcmd.go | 7 +------ cmd/geth/snapshot.go | 10 ++-------- core/rawdb/accessors_trie.go | 35 ++++------------------------------- core/rawdb/ancient_utils.go | 3 ++- core/rawdb/database.go | 14 ++++++++++++++ core/rawdb/table.go | 4 ++++ ethdb/database.go | 5 +++++ ethdb/remotedb/remotedb.go | 4 ++++ node/node.go | 14 +++----------- trie/database.go | 5 +---- 11 files changed, 41 insertions(+), 62 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 1a59f999b7..2ce1200e74 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -239,7 +239,7 @@ func initGenesis(ctx *cli.Context) error { // if the trie data dir has been set, new trie db with a new state database if ctx.IsSet(utils.SeparateDBFlag.Name) { - statediskdb, dbErr := stack.OpenDatabaseWithFreezer(name, 0, 0, "", "", false, false, false, false, true) + statediskdb, dbErr := stack.OpenDatabaseWithFreezer(name+"/state", 0, 0, "", "", false, false, false, false, true) if dbErr != nil { utils.Fatalf("Failed to open separate trie database: %v", dbErr) } diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index 94f3883367..17841cfdda 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -420,12 +420,7 @@ func inspectTrie(ctx *cli.Context) error { } fmt.Printf("ReadBlockHeader, root: %v, blocknum: %v\n", trieRootHash, blockNumber) - var dbScheme string - if db.StateStore() != nil { - dbScheme = rawdb.ReadStateSchemeByStateDB(db, db.StateStore()) - } else { - dbScheme = rawdb.ReadStateScheme(db) - } + dbScheme := rawdb.ReadStateScheme(db) var config *trie.Config if dbScheme == rawdb.PathScheme { config = &trie.Config{ diff --git a/cmd/geth/snapshot.go b/cmd/geth/snapshot.go index 781c78ed1c..8d9506d842 100644 --- a/cmd/geth/snapshot.go +++ b/cmd/geth/snapshot.go @@ -441,14 +441,8 @@ func pruneState(ctx *cli.Context) error { BloomSize: ctx.Uint64(utils.BloomFilterSizeFlag.Name), } - if chaindb.StateStore() != nil { - if rawdb.ReadStateSchemeByStateDB(chaindb, chaindb.StateStore()) != rawdb.HashScheme { - log.Crit("Offline pruning is not required for path scheme") - } - } else { - if rawdb.ReadStateScheme(chaindb) != rawdb.HashScheme { - log.Crit("Offline pruning is not required for path scheme") - } + if rawdb.ReadStateScheme(chaindb) != rawdb.HashScheme { + log.Crit("Offline pruning is not required for path scheme") } pruner, err := pruner.NewPruner(chaindb, prunerconfig, ctx.Uint64(utils.TriesInMemoryFlag.Name)) diff --git a/core/rawdb/accessors_trie.go b/core/rawdb/accessors_trie.go index bb62ac0aef..35ede96643 100644 --- a/core/rawdb/accessors_trie.go +++ b/core/rawdb/accessors_trie.go @@ -288,13 +288,13 @@ func DeleteTrieNode(db ethdb.KeyValueWriter, owner common.Hash, path []byte, has // if the state is not present in database. func ReadStateScheme(db ethdb.Reader) string { // Check if state in path-based scheme is present - blob, _ := ReadAccountTrieNode(db, nil) + blob, _ := ReadAccountTrieNode(db.StateStoreReader(), nil) if len(blob) != 0 { return PathScheme } // The root node might be deleted during the initial snap sync, check // the persistent state id then. - if id := ReadPersistentStateID(db); id != 0 { + if id := ReadPersistentStateID(db.StateStoreReader()); id != 0 { return PathScheme } // In a hash-based scheme, the genesis state is consistently stored @@ -304,29 +304,7 @@ func ReadStateScheme(db ethdb.Reader) string { if header == nil { return "" // empty datadir } - blob = ReadLegacyTrieNode(db, header.Root) - if len(blob) == 0 { - return "" // no state in disk - } - return HashScheme -} - -// ReadStateSchemeByStateDB reads the state scheme of persistent state from state disk db, or none -// if the state is not present in database -func ReadStateSchemeByStateDB(db, statediskdb ethdb.Reader) string { - // Check if state in path-based scheme is present - blob, _ := ReadAccountTrieNode(statediskdb, nil) - if len(blob) != 0 { - return PathScheme - } - // In a hash-based scheme, the genesis state is consistently stored - // on the disk. To assess the scheme of the persistent state, it - // suffices to inspect the scheme of the genesis state. - header := ReadHeader(db, ReadCanonicalHash(db, 0), 0) - if header == nil { - return "" // empty datadir - } - blob = ReadLegacyTrieNode(statediskdb, header.Root) + blob = ReadLegacyTrieNode(db.StateStoreReader(), header.Root) if len(blob) == 0 { return "" // no state in disk } @@ -357,12 +335,7 @@ func ParseStateScheme(provided string, disk ethdb.Database) (string, error) { // If state scheme is not specified, use the scheme consistent // with persistent state, or fallback to hash mode if database // is empty. - var stored string - if disk != nil && disk.StateStore() != nil { - stored = ReadStateSchemeByStateDB(disk, disk.StateStore()) - } else { - stored = ReadStateScheme(disk) - } + stored := ReadStateScheme(disk) if provided == "" { if stored == "" { // use default scheme for empty database, flip it when diff --git a/core/rawdb/ancient_utils.go b/core/rawdb/ancient_utils.go index a73e586192..f7a0208d38 100644 --- a/core/rawdb/ancient_utils.go +++ b/core/rawdb/ancient_utils.go @@ -91,7 +91,8 @@ func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) { infos = append(infos, info) case StateFreezerName: - if ReadStateScheme(db) != PathScheme { + if + ReadStateScheme(db) != PathScheme { continue } datadir, err := db.AncientDatadir() diff --git a/core/rawdb/database.go b/core/rawdb/database.go index 0811f170d4..80082830f9 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -45,6 +45,13 @@ type freezerdb struct { stateStore ethdb.Database } +func (frdb *freezerdb) StateStoreReader() ethdb.Reader { + if frdb.stateStore == nil { + return frdb + } + return frdb.stateStore +} + // AncientDatadir returns the path of root ancient directory. func (frdb *freezerdb) AncientDatadir() (string, error) { return frdb.ancientRoot, nil @@ -196,6 +203,13 @@ func (db *nofreezedb) SetStateStore(state ethdb.Database) { db.stateStore = state } +func (db *nofreezedb) StateStoreReader() ethdb.Reader { + if db.stateStore != nil { + return db.stateStore + } + return db +} + func (db *nofreezedb) ReadAncients(fn func(reader ethdb.AncientReaderOp) error) (err error) { // Unlike other ancient-related methods, this method does not return // errNotSupported when invoked. diff --git a/core/rawdb/table.go b/core/rawdb/table.go index 8b81329f35..dc49d526c3 100644 --- a/core/rawdb/table.go +++ b/core/rawdb/table.go @@ -221,6 +221,10 @@ func (t *table) SetStateStore(state ethdb.Database) { panic("not implement") } +func (t *table) StateStoreReader() ethdb.Reader { + return nil +} + // NewBatchWithSize creates a write-only database batch with pre-allocated buffer. func (t *table) NewBatchWithSize(size int) ethdb.Batch { return &tableBatch{t.db.NewBatchWithSize(size), t.prefix} diff --git a/ethdb/database.go b/ethdb/database.go index 12404a521c..cb694fe420 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -155,11 +155,16 @@ type AncientStater interface { AncientDatadir() (string, error) } +type StateStoreReader interface { + StateStoreReader() Reader +} + // Reader contains the methods required to read data from both key-value as well as // immutable ancient data. type Reader interface { KeyValueReader AncientReader + StateStoreReader } // Writer contains the methods required to write data to both key-value as well as diff --git a/ethdb/remotedb/remotedb.go b/ethdb/remotedb/remotedb.go index b4f84e28aa..0214126153 100644 --- a/ethdb/remotedb/remotedb.go +++ b/ethdb/remotedb/remotedb.go @@ -102,6 +102,10 @@ func (db *Database) SetStateStore(state ethdb.Database) { panic("not supported") } +func (db *Database) StateStoreReader() ethdb.Reader { + return db +} + func (db *Database) ReadAncients(fn func(op ethdb.AncientReaderOp) error) (err error) { return fn(db) } diff --git a/node/node.go b/node/node.go index 6bd59a6d99..dbd4f7a889 100644 --- a/node/node.go +++ b/node/node.go @@ -789,7 +789,7 @@ func (n *Node) OpenAndMergeDatabase(name string, cache, handles int, freezer, di // Open the separated state database if the state directory exists if n.HasSeparateTrieDir() { // Allocate half of the handles and cache to this separate state data database - statediskdb, err = n.OpenDatabaseWithFreezer(name, cache/2, chainDataHandles/2, "", "eth/db/statedata/", readonly, false, false, pruneAncientData, true) + statediskdb, err = n.OpenDatabaseWithFreezer(name+"/state", cache/2, chainDataHandles/2, "", "eth/db/statedata/", readonly, false, false, pruneAncientData, true) if err != nil { return nil, err } @@ -838,18 +838,10 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient, } db = rawdb.NewMemoryDatabase() } else { - var dirName, ancientDirName string - if isSeparateStateDB { - dirName = filepath.Join(n.ResolvePath(name), "state") - ancientDirName = filepath.Join(dirName, "ancient") - } else { - dirName = n.ResolvePath(name) - ancientDirName = n.ResolveAncient(name, ancient) - } db, err = rawdb.Open(rawdb.OpenOptions{ Type: n.config.DBEngine, - Directory: dirName, - AncientsDirectory: ancientDirName, + Directory: n.ResolvePath(name), + AncientsDirectory: n.ResolveAncient(name, ancient), Namespace: namespace, Cache: cache, Handles: handles, diff --git a/trie/database.go b/trie/database.go index bd35d19351..d19e83e7b4 100644 --- a/trie/database.go +++ b/trie/database.go @@ -91,16 +91,13 @@ type Database struct { // the legacy hash-based scheme is used by default. func NewDatabase(diskdb ethdb.Database, config *Config) *Database { // Sanitize the config and use the default one if it's not specified. - var dbScheme string var triediskdb ethdb.Database if diskdb != nil && diskdb.StateStore() != nil { - dbScheme = rawdb.ReadStateSchemeByStateDB(diskdb, diskdb.StateStore()) triediskdb = diskdb.StateStore() } else { - dbScheme = rawdb.ReadStateScheme(diskdb) triediskdb = diskdb } - + dbScheme := rawdb.ReadStateScheme(diskdb) if config == nil { if dbScheme == rawdb.PathScheme { config = &Config{