From 79305da2556b393706632e44da22e80955816b4d Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Wed, 29 Nov 2023 16:41:40 +0800 Subject: [PATCH 01/18] feat: support separate db for trie --- cmd/geth/chaincmd.go | 17 +++++++++-- cmd/utils/flags.go | 10 +++++++ core/blockchain.go | 67 ++++++++++++++++++++++++++++---------------- eth/backend.go | 10 +++++++ node/config.go | 10 +++++++ node/node.go | 31 ++++++++++++++++++++ 6 files changed, 119 insertions(+), 26 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 1b88aecb52..cd94d34050 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -237,8 +237,21 @@ func initGenesis(ctx *cli.Context) error { } defer chaindb.Close() - triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle()) - defer triedb.Close() + var triedb *trie.Database + // if the trie datadir has been set , new triedb with a new chaindb + if ctx.IsSet(utils.TrieDirFlag.Name) { + newChaindb, dbErr := stack.OpenDatabaseForTrie(name, 0, 0, "", "", false, false, false, false) + if dbErr != nil { + utils.Fatalf("Failed to open database: %v", err) + } + defer newChaindb.Close() + + triedb = utils.MakeTrieDatabase(ctx, newChaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false) + defer triedb.Close() + } else { + triedb = utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false) + defer triedb.Close() + } _, hash, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides) if err != nil { diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 3514734c90..82aac11736 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -93,6 +93,13 @@ var ( Value: flags.DirectoryString(node.DefaultDataDir()), Category: flags.EthCategory, } + + TrieDirFlag = &flags.DirectoryFlag{ + Name: "triedir", + Usage: "Data directory for the trie data base", + Value: flags.DirectoryString(node.DefaultDataDir() + "trie"), + Category: flags.EthCategory, + } DirectBroadcastFlag = &cli.BoolFlag{ Name: "directbroadcast", Usage: "Enable directly broadcast mined block to all peers", @@ -1112,6 +1119,7 @@ var ( DBEngineFlag, StateSchemeFlag, HttpHeaderFlag, + TrieDirFlag, } ) @@ -1630,6 +1638,8 @@ func SetDataDir(ctx *cli.Context, cfg *node.Config) { switch { case ctx.IsSet(DataDirFlag.Name): cfg.DataDir = ctx.String(DataDirFlag.Name) + case ctx.IsSet(TrieDirFlag.Name): + cfg.TrieDir = ctx.String(TrieDirFlag.Name) case ctx.Bool(DeveloperFlag.Name): cfg.DataDir = "" // unless explicitly requested, use memory databases } diff --git a/core/blockchain.go b/core/blockchain.go index 5141169986..b186554c17 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -240,7 +240,8 @@ type BlockChain struct { chainConfig *params.ChainConfig // Chain & network configuration cacheConfig *CacheConfig // Cache configuration for pruning - db ethdb.Database // Low level persistent database to store final content in + db ethdb.Database // Low level persistent database to store final content in + separateDB ethdb.Database snaps *snapshot.Tree // Snapshot tree for fast trie leaf access triegc *prque.Prque[int64, common.Hash] // Priority queue mapping block numbers to tries to gc gcproc time.Duration // Accumulates canonical block processing for trie dumping @@ -324,17 +325,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis diffLayerCache, _ := exlru.New(diffLayerCacheLimit) diffLayerChanCache, _ := exlru.New(diffLayerCacheLimit) - // Open trie database with provided config - triedb := trie.NewDatabase(db, cacheConfig.triedbConfig()) - // Setup the genesis block, commit the provided genesis specification - // to database if the genesis block is not present yet, or load the - // stored one from database. - chainConfig, genesisHash, genesisErr := SetupGenesisBlockWithOverride(db, triedb, genesis, overrides) - if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { - return nil, genesisErr - } - systemcontracts.GenesisHash = genesisHash - log.Info("Initialised chain configuration", "config", chainConfig) // Description of chainConfig is empty now /* log.Info("") @@ -347,10 +337,10 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis */ bc := &BlockChain{ - chainConfig: chainConfig, - cacheConfig: cacheConfig, - db: db, - triedb: triedb, + // chainConfig: chainConfig, + cacheConfig: cacheConfig, + db: db, + // triedb: triedb, triegc: prque.New[int64, common.Hash](nil), quit: make(chan struct{}), triesInMemory: cacheConfig.TriesInMemory, @@ -369,6 +359,35 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis diffQueue: prque.New[int64, *types.DiffLayer](nil), diffQueueBuffer: make(chan *types.DiffLayer), } + var err error + // do options before start any routine + for _, option := range options { + bc, err = option(bc) + if err != nil { + return nil, err + } + } + + // Open trie database with provided config + var triedb *trie.Database + if bc.separateDB != nil { + fmt.Printf("the separate db of block chain has been setted") + triedb = trie.NewDatabase(bc.separateDB, cacheConfig.triedbConfig()) + } else { + triedb = trie.NewDatabase(db, cacheConfig.triedbConfig()) + } + bc.triedb = triedb + // Setup the genesis block, commit the provided genesis specification + // to database if the genesis block is not present yet, or load the + // stored one from database. + chainConfig, genesisHash, genesisErr := SetupGenesisBlockWithOverride(db, triedb, genesis, overrides) + if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { + return nil, genesisErr + } + systemcontracts.GenesisHash = genesisHash + log.Info("Initialised chain configuration", "config", chainConfig) + bc.chainConfig = chainConfig + bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit)) bc.forker = NewForkChoice(bc, shouldPreserve) bc.stateCache = state.NewDatabaseWithNodeDB(bc.db, bc.triedb) @@ -376,7 +395,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis bc.prefetcher = NewStatePrefetcher(chainConfig, bc, engine) bc.processor = NewStateProcessor(chainConfig, bc, engine) - var err error bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.insertStopped) if err != nil { return nil, err @@ -524,13 +542,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis } bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root, int(bc.cacheConfig.TriesInMemory), bc.NoTries()) } - // do options before start any routine - for _, option := range options { - bc, err = option(bc) - if err != nil { - return nil, err - } - } + // Start future block processor. bc.wg.Add(1) go bc.updateFutureBlocks() @@ -2859,6 +2871,13 @@ func EnablePipelineCommit(bc *BlockChain) (*BlockChain, error) { return bc, nil } +func EnableSeparateDB(separateDB ethdb.Database) BlockChainOption { + return func(chain *BlockChain) (*BlockChain, error) { + chain.separateDB = separateDB + return chain, nil + } +} + func EnablePersistDiff(limit uint64) BlockChainOption { return func(chain *BlockChain) (*BlockChain, error) { chain.diffLayerFreezerBlockLimit = limit diff --git a/eth/backend.go b/eth/backend.go index d60e24605c..b471b9abfc 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -272,6 +272,16 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { bcOps = append(bcOps, core.EnableDoubleSignChecker) } + if stack.Config().TrieDir != "" { + fmt.Println("trie data dir has setted to ", stack.Config().TrieDir) + newChainDb, err := stack.OpenDatabaseForTrie("chaindata", config.DatabaseCache, config.DatabaseHandles, + config.DatabaseFreezer, "eth/db/chaindata/", false, false, false, config.PruneAncientData) + if err != nil { + return nil, err + } + bcOps = append(bcOps, core.EnableSeparateDB(newChainDb)) + } + peers := newPeerSet() bcOps = append(bcOps, core.EnableBlockValidator(chainConfig, eth.engine, config.TriesVerifyMode, peers)) eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, eth.shouldPreserve, &config.TransactionHistory, bcOps...) diff --git a/node/config.go b/node/config.go index bc30a0ab0a..b795958078 100644 --- a/node/config.go +++ b/node/config.go @@ -64,6 +64,9 @@ type Config struct { // in memory. DataDir string + // TrieDir is the file system folder the node should use for storing trie data. + TrieDir string + // Configuration of peer-to-peer networking. P2P p2p.Config @@ -393,6 +396,13 @@ func (c *Config) instanceDir() string { return filepath.Join(c.DataDir, c.name()) } +func (c *Config) trieDir() string { + if c.TrieDir == "" { + return "" + } + return filepath.Join(c.TrieDir, c.name()) +} + // NodeKey retrieves the currently configured private key of the node, checking // first any manually set key, falling back to the one found in the configured // data folder. If no key can be found, a new one is generated. diff --git a/node/node.go b/node/node.go index 2c8e6f0f88..2c051bb1d0 100644 --- a/node/node.go +++ b/node/node.go @@ -835,6 +835,37 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient, return db, err } +func (n *Node) OpenDatabaseForTrie(name string, cache, handles int, ancient, namespace string, readonly, disableFreeze, isLastOffset, pruneAncientData bool) (ethdb.Database, error) { + n.lock.Lock() + defer n.lock.Unlock() + if n.state == closedState { + return nil, ErrNodeStopped + } + var db ethdb.Database + var err error + if n.config.DataDir == "" { + db = rawdb.NewMemoryDatabase() + } else { + db, err = rawdb.Open(rawdb.OpenOptions{ + Type: n.config.DBEngine, + Directory: n.config.TrieDir, + AncientsDirectory: filepath.Join(n.config.trieDir(), "ancient"), + Namespace: namespace, + Cache: cache, + Handles: handles, + ReadOnly: readonly, + DisableFreeze: disableFreeze, + IsLastOffset: isLastOffset, + PruneAncientData: pruneAncientData, + }) + } + + if err == nil { + db = n.wrapDatabase(db) + } + return db, err +} + func (n *Node) OpenDiffDatabase(name string, handles int, diff, namespace string, readonly bool) (*leveldb.Database, error) { n.lock.Lock() defer n.lock.Unlock() From 50d1377df59e7b00754ebc7d58178e8ee1ac0214 Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Thu, 30 Nov 2023 11:38:38 +0800 Subject: [PATCH 02/18] fix: add log --- cmd/geth/chaincmd.go | 2 +- cmd/utils/flags.go | 10 ++++++++++ core/blockchain.go | 6 ++++-- core/state/state_object.go | 1 + eth/backend.go | 3 ++- miner/stress/clique/main.go | 2 +- node/node.go | 10 ++++++++-- 7 files changed, 27 insertions(+), 7 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index cd94d34050..fb7a62204b 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -242,7 +242,7 @@ func initGenesis(ctx *cli.Context) error { if ctx.IsSet(utils.TrieDirFlag.Name) { newChaindb, dbErr := stack.OpenDatabaseForTrie(name, 0, 0, "", "", false, false, false, false) if dbErr != nil { - utils.Fatalf("Failed to open database: %v", err) + utils.Fatalf("Failed to open separate trie database: %v", dbErr) } defer newChaindb.Close() diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 82aac11736..af6ebe61d7 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1639,6 +1639,7 @@ func SetDataDir(ctx *cli.Context, cfg *node.Config) { case ctx.IsSet(DataDirFlag.Name): cfg.DataDir = ctx.String(DataDirFlag.Name) case ctx.IsSet(TrieDirFlag.Name): + fmt.Println("setting TrieDirFlag.Name") cfg.TrieDir = ctx.String(TrieDirFlag.Name) case ctx.Bool(DeveloperFlag.Name): cfg.DataDir = "" // unless explicitly requested, use memory databases @@ -2142,6 +2143,15 @@ func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) { // RegisterEthService adds an Ethereum client to the stack. // The second return value is the full node instance. func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend, *eth.Ethereum) { + if cfg.SyncMode == downloader.LightSync { + backend, err := les.New(stack, cfg) + if err != nil { + Fatalf("Failed to register the Ethereum service: %v", err) + } + stack.RegisterAPIs(tracers.APIs(backend.ApiBackend)) + return backend.ApiBackend, nil + } + backend, err := eth.New(stack, cfg) if err != nil { Fatalf("Failed to register the Ethereum service: %v", err) diff --git a/core/blockchain.go b/core/blockchain.go index b186554c17..d18387fa6b 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -371,7 +371,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis // Open trie database with provided config var triedb *trie.Database if bc.separateDB != nil { - fmt.Printf("the separate db of block chain has been setted") + log.Info("the separate db of block chain has been set") triedb = trie.NewDatabase(bc.separateDB, cacheConfig.triedbConfig()) } else { triedb = trie.NewDatabase(db, cacheConfig.triedbConfig()) @@ -2873,7 +2873,9 @@ func EnablePipelineCommit(bc *BlockChain) (*BlockChain, error) { func EnableSeparateDB(separateDB ethdb.Database) BlockChainOption { return func(chain *BlockChain) (*BlockChain, error) { - chain.separateDB = separateDB + if separateDB != nil { + chain.separateDB = separateDB + } return chain, nil } } diff --git a/core/state/state_object.go b/core/state/state_object.go index 524bdc47cd..02e4d5623e 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -183,6 +183,7 @@ func (s *stateObject) getOriginStorage(key common.Hash) (common.Hash, bool) { if value, cached := s.originStorage[key]; cached { return value, true } + // if L1 cache miss, try to get it from shared pool if s.sharedOriginStorage != nil { val, ok := s.sharedOriginStorage.Load(key) diff --git a/eth/backend.go b/eth/backend.go index b471b9abfc..f9a0ccce20 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -271,12 +271,13 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if stack.Config().EnableDoubleSignMonitor { bcOps = append(bcOps, core.EnableDoubleSignChecker) } - + log.Info("trie dir is :" + stack.Config().TrieDir) if stack.Config().TrieDir != "" { fmt.Println("trie data dir has setted to ", stack.Config().TrieDir) newChainDb, err := stack.OpenDatabaseForTrie("chaindata", config.DatabaseCache, config.DatabaseHandles, config.DatabaseFreezer, "eth/db/chaindata/", false, false, false, config.PruneAncientData) if err != nil { + log.Info("open db err", err) return nil, err } bcOps = append(bcOps, core.EnableSeparateDB(newChainDb)) diff --git a/miner/stress/clique/main.go b/miner/stress/clique/main.go index ead3d8df35..2f11b4aa97 100644 --- a/miner/stress/clique/main.go +++ b/miner/stress/clique/main.go @@ -183,7 +183,7 @@ func makeGenesis(faucets []*ecdsa.PrivateKey, sealers []*ecdsa.PrivateKey) *core func makeSealer(genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) { // Define the basic configurations for the Ethereum node datadir, _ := os.MkdirTemp("", "") - + log.Info("making sealer") config := &node.Config{ Name: "geth", Version: params.Version, diff --git a/node/node.go b/node/node.go index 2c051bb1d0..ec889fbf94 100644 --- a/node/node.go +++ b/node/node.go @@ -90,6 +90,7 @@ func New(conf *Config) (*Node, error) { } conf.DataDir = absdatadir } + if conf.LogConfig != nil { if conf.LogConfig.TermTimeFormat != nil && *conf.LogConfig.TermTimeFormat != "" { log.SetTermTimeFormat(*conf.LogConfig.TermTimeFormat) @@ -838,18 +839,23 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient, func (n *Node) OpenDatabaseForTrie(name string, cache, handles int, ancient, namespace string, readonly, disableFreeze, isLastOffset, pruneAncientData bool) (ethdb.Database, error) { n.lock.Lock() defer n.lock.Unlock() + fmt.Println(":q!"+ + ":qtrie database dir0:", n.config.TrieDir) if n.state == closedState { return nil, ErrNodeStopped } var db ethdb.Database var err error if n.config.DataDir == "" { + fmt.Println("trie database dir1:", n.config.TrieDir) db = rawdb.NewMemoryDatabase() } else { + direcrory := filepath.Join(n.config.trieDir(), name) + fmt.Println("trie database dir2c:", direcrory) db, err = rawdb.Open(rawdb.OpenOptions{ Type: n.config.DBEngine, - Directory: n.config.TrieDir, - AncientsDirectory: filepath.Join(n.config.trieDir(), "ancient"), + Directory: direcrory, + AncientsDirectory: filepath.Join(direcrory, "ancient"), Namespace: namespace, Cache: cache, Handles: handles, From 1dfa81d5d3c5868bc936dbe3fec256f1de911067 Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Tue, 5 Dec 2023 15:08:09 +0800 Subject: [PATCH 03/18] fix: fix trie dir init error --- cmd/utils/flags.go | 2 +- eth/backend.go | 2 +- node/config.go | 4 ++++ node/node.go | 8 ++++---- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index af6ebe61d7..544a61c1de 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1639,7 +1639,7 @@ func SetDataDir(ctx *cli.Context, cfg *node.Config) { case ctx.IsSet(DataDirFlag.Name): cfg.DataDir = ctx.String(DataDirFlag.Name) case ctx.IsSet(TrieDirFlag.Name): - fmt.Println("setting TrieDirFlag.Name") + fmt.Println("setting TrieDirFlag.Name", ctx.String(TrieDirFlag.Name)) cfg.TrieDir = ctx.String(TrieDirFlag.Name) case ctx.Bool(DeveloperFlag.Name): cfg.DataDir = "" // unless explicitly requested, use memory databases diff --git a/eth/backend.go b/eth/backend.go index f9a0ccce20..df0aab47bd 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -271,7 +271,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if stack.Config().EnableDoubleSignMonitor { bcOps = append(bcOps, core.EnableDoubleSignChecker) } - log.Info("trie dir is :" + stack.Config().TrieDir) + if stack.Config().TrieDir != "" { fmt.Println("trie data dir has setted to ", stack.Config().TrieDir) newChainDb, err := stack.OpenDatabaseForTrie("chaindata", config.DatabaseCache, config.DatabaseHandles, diff --git a/node/config.go b/node/config.go index b795958078..16c01fdad7 100644 --- a/node/config.go +++ b/node/config.go @@ -448,6 +448,10 @@ func (c *Config) checkLegacyFiles() { c.checkLegacyFile(c.ResolvePath(datadirTrustedNodes)) } +func (c *Config) enableSeparateTrie(trieDir string) { + c.TrieDir = trieDir +} + // checkLegacyFile will only raise an error if a file at the given path exists. func (c *Config) checkLegacyFile(path string) { // Short circuit if no node config is present diff --git a/node/node.go b/node/node.go index ec889fbf94..220836348a 100644 --- a/node/node.go +++ b/node/node.go @@ -180,6 +180,10 @@ func New(conf *Config) (*Node, error) { node.server.Config.NodeDatabase = node.config.NodeDB() } + if conf.TrieDir != "" { + node.config.enableSeparateTrie(conf.TrieDir) + } + // Check HTTP/WS prefixes are valid. if err := validatePrefix("HTTP", conf.HTTPPathPrefix); err != nil { return nil, err @@ -839,19 +843,15 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient, func (n *Node) OpenDatabaseForTrie(name string, cache, handles int, ancient, namespace string, readonly, disableFreeze, isLastOffset, pruneAncientData bool) (ethdb.Database, error) { n.lock.Lock() defer n.lock.Unlock() - fmt.Println(":q!"+ - ":qtrie database dir0:", n.config.TrieDir) if n.state == closedState { return nil, ErrNodeStopped } var db ethdb.Database var err error if n.config.DataDir == "" { - fmt.Println("trie database dir1:", n.config.TrieDir) db = rawdb.NewMemoryDatabase() } else { direcrory := filepath.Join(n.config.trieDir(), name) - fmt.Println("trie database dir2c:", direcrory) db, err = rawdb.Open(rawdb.OpenOptions{ Type: n.config.DBEngine, Directory: direcrory, From 1eecb3c412e16236475fdb326b0da1b129585680 Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Tue, 5 Dec 2023 15:22:43 +0800 Subject: [PATCH 04/18] fix: fix db inspect command --- core/rawdb/database.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/rawdb/database.go b/core/rawdb/database.go index e7e53947f6..7f8608f399 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -659,14 +659,14 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { bodies.Add(size) case bytes.HasPrefix(key, blockReceiptsPrefix) && len(key) == (len(blockReceiptsPrefix)+8+common.HashLength): receipts.Add(size) + case IsLegacyTrieNode(key, it.Value()): + legacyTries.Add(size) case bytes.HasPrefix(key, headerPrefix) && bytes.HasSuffix(key, headerTDSuffix): tds.Add(size) case bytes.HasPrefix(key, headerPrefix) && bytes.HasSuffix(key, headerHashSuffix): numHashPairings.Add(size) case bytes.HasPrefix(key, headerNumberPrefix) && len(key) == (len(headerNumberPrefix)+common.HashLength): hashNumPairings.Add(size) - case IsLegacyTrieNode(key, it.Value()): - legacyTries.Add(size) case bytes.HasPrefix(key, stateIDPrefix) && len(key) == len(stateIDPrefix)+common.HashLength: stateLookups.Add(size) case IsAccountTrieNode(key): From 79143db7162d237aa829a1f13a1730777c4ee6a5 Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Mon, 4 Dec 2023 19:24:33 +0800 Subject: [PATCH 05/18] refactor: delete the trie datadir flag and make it fixed --- cmd/geth/chaincmd.go | 10 ++--- cmd/geth/dbcmd.go | 76 ++++++++++++++++++++++++++++++++---- cmd/geth/snapshot.go | 32 +++++++++++++++ cmd/utils/flags.go | 37 +++++++++--------- core/blockchain.go | 78 +++++++++++++++++++++++-------------- core/rawdb/database.go | 68 +++++++++++++++++++++++++++++++- core/state/state_object.go | 1 - eth/backend.go | 55 +++++++++++++++++++------- miner/stress/clique/main.go | 1 - node/config.go | 15 ++----- node/node.go | 49 +++++++++++++---------- 11 files changed, 315 insertions(+), 107 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index fb7a62204b..8d00beb778 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -238,15 +238,15 @@ func initGenesis(ctx *cli.Context) error { defer chaindb.Close() var triedb *trie.Database - // if the trie datadir has been set , new triedb with a new chaindb - if ctx.IsSet(utils.TrieDirFlag.Name) { - newChaindb, dbErr := stack.OpenDatabaseForTrie(name, 0, 0, "", "", false, false, false, false) + // if the trie data dir has been set , new trie db with a new trie database + if ctx.IsSet(utils.SeparateDBFlag.Name) { + separatedDB, dbErr := stack.OpenTrieDataBase(name, 0, 0, "", false, false, false, false) if dbErr != nil { utils.Fatalf("Failed to open separate trie database: %v", dbErr) } - defer newChaindb.Close() + defer separatedDB.Close() - triedb = utils.MakeTrieDatabase(ctx, newChaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false) + triedb = utils.MakeTrieDatabase(ctx, separatedDB, ctx.Bool(utils.CachePreimagesFlag.Name), false) defer triedb.Close() } else { triedb = utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false) diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index 677bae5d12..40a7363798 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -381,7 +381,11 @@ func inspectTrie(ctx *cli.Context) error { db := utils.MakeChainDatabase(ctx, stack, true, false) defer db.Close() - + var separateTrie ethdb.Database + if stack.HasSeparateTrieDir() { + separateTrie = utils.MakeSeparateTrieDB(ctx, stack, true, false) + defer separateTrie.Close() + } var headerBlockHash common.Hash if ctx.NArg() >= 1 { if ctx.Args().Get(0) == "latest" { @@ -431,7 +435,12 @@ func inspectTrie(ctx *cli.Context) error { config = trie.HashDefaults } - triedb := trie.NewDatabase(db, config) + var triedb *trie.Database + if separateTrie != nil { + triedb = trie.NewDatabase(separateTrie, config) + } else { + triedb = trie.NewDatabase(db, config) + } theTrie, err := trie.New(trie.TrieID(trieRootHash), triedb) if err != nil { fmt.Printf("fail to new trie tree, err: %v, rootHash: %v\n", err, trieRootHash.String()) @@ -475,7 +484,12 @@ func inspect(ctx *cli.Context) error { db := utils.MakeChainDatabase(ctx, stack, true, false) defer db.Close() - return rawdb.InspectDatabase(db, prefix, start) + var seprateDB ethdb.Database + if stack.HasSeparateTrieDir() { + seprateDB = utils.MakeSeparateTrieDB(ctx, stack, true, false) + defer seprateDB.Close() + } + return rawdb.InspectDatabase(db, seprateDB, prefix, start) } func ancientInspect(ctx *cli.Context) error { @@ -562,6 +576,13 @@ func dbStats(ctx *cli.Context) error { defer db.Close() showLeveldbStats(db) + if stack.HasSeparateTrieDir() { + seprateTrieDB := utils.MakeSeparateTrieDB(ctx, stack, true, false) + defer seprateTrieDB.Close() + fmt.Println("show stats of separated db") + showLeveldbStats(seprateTrieDB) + } + return nil } @@ -575,13 +596,29 @@ func dbCompact(ctx *cli.Context) error { log.Info("Stats before compaction") showLeveldbStats(db) + var separateTrieDB ethdb.Database + if stack.HasSeparateTrieDir() { + separateTrieDB = utils.MakeSeparateTrieDB(ctx, stack, false, false) + defer separateTrieDB.Close() + showLeveldbStats(separateTrieDB) + } + log.Info("Triggering compaction") if err := db.Compact(nil, nil); err != nil { - log.Info("Compact err", "error", err) + log.Error("Compact err", "error", err) + return err + } + + if err := separateTrieDB.Compact(nil, nil); err != nil { + log.Error("Compact err", "error", err) return err } + log.Info("Stats after compaction") showLeveldbStats(db) + if separateTrieDB != nil { + showLeveldbStats(separateTrieDB) + } return nil } @@ -604,6 +641,16 @@ func dbGet(ctx *cli.Context) error { data, err := db.Get(key) if err != nil { + // if separate trie db exist, try to get it from separate db + if stack.HasSeparateTrieDir() { + trieDB := utils.MakeSeparateTrieDB(ctx, stack, true, false) + defer trieDB.Close() + triedata, dberr := trieDB.Get(key) + if dberr == nil { + fmt.Printf("key %#x: %#x\n", key, triedata) + return nil + } + } log.Info("Get operation failed", "key", fmt.Sprintf("%#x", key), "error", err) return err } @@ -619,7 +666,12 @@ func dbTrieGet(ctx *cli.Context) error { stack, _ := makeConfigNode(ctx) defer stack.Close() - db := utils.MakeChainDatabase(ctx, stack, false, false) + var db ethdb.Database + if stack.HasSeparateTrieDir() { + db = utils.MakeSeparateTrieDB(ctx, stack, true, false) + } else { + db = utils.MakeChainDatabase(ctx, stack, true, false) + } defer db.Close() scheme := ctx.String(utils.StateSchemeFlag.Name) @@ -685,7 +737,12 @@ func dbTrieDelete(ctx *cli.Context) error { stack, _ := makeConfigNode(ctx) defer stack.Close() - db := utils.MakeChainDatabase(ctx, stack, false, false) + var db ethdb.Database + if stack.HasSeparateTrieDir() { + db = utils.MakeSeparateTrieDB(ctx, stack, true, false) + } else { + db = utils.MakeChainDatabase(ctx, stack, true, false) + } defer db.Close() scheme := ctx.String(utils.StateSchemeFlag.Name) @@ -807,7 +864,12 @@ func dbDumpTrie(ctx *cli.Context) error { stack, _ := makeConfigNode(ctx) defer stack.Close() - db := utils.MakeChainDatabase(ctx, stack, true, false) + var db ethdb.Database + if stack.HasSeparateTrieDir() { + db = utils.MakeSeparateTrieDB(ctx, stack, true, false) + } else { + db = utils.MakeChainDatabase(ctx, stack, true, false) + } defer db.Close() triedb := utils.MakeTrieDatabase(ctx, db, false, true, false) diff --git a/cmd/geth/snapshot.go b/cmd/geth/snapshot.go index 73453c0f91..97363237b0 100644 --- a/cmd/geth/snapshot.go +++ b/cmd/geth/snapshot.go @@ -685,7 +685,18 @@ func traverseRawState(ctx *cli.Context) error { chaindb := utils.MakeChainDatabase(ctx, stack, true, false) defer chaindb.Close() +<<<<<<< HEAD triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false) +======= + var triedb *trie.Database + if stack.HasSeparateTrieDir() { + separateTrie := utils.MakeSeparateTrieDB(ctx, stack, true, false) + defer separateTrie.Close() + triedb = utils.MakeTrieDatabase(ctx, separateTrie, false, true) + } else { + triedb = utils.MakeTrieDatabase(ctx, chaindb, false, true) + } +>>>>>>> b5a9db378 (refactor: delete the trie datadir flag and make it fixed) defer triedb.Close() headBlock := rawdb.ReadHeadBlock(chaindb) @@ -849,7 +860,18 @@ func dumpState(ctx *cli.Context) error { if err != nil { return err } +<<<<<<< HEAD triedb := utils.MakeTrieDatabase(ctx, db, false, true, false) +======= + + var separateTrie ethdb.Database + if stack.HasSeparateTrieDir() { + separateTrie = utils.MakeSeparateTrieDB(ctx, stack, true, false) + defer separateTrie.Close() + } + + triedb := utils.MakeTrieDatabase(ctx, db, false, true) +>>>>>>> b5a9db378 (refactor: delete the trie datadir flag and make it fixed) defer triedb.Close() snapConfig := snapshot.Config{ @@ -859,7 +881,17 @@ func dumpState(ctx *cli.Context) error { AsyncBuild: false, } triesInMemory := ctx.Uint64(utils.TriesInMemoryFlag.Name) +<<<<<<< HEAD snaptree, err := snapshot.New(snapConfig, db, triedb, root, int(triesInMemory), false) +======= + + var snaptree *snapshot.Tree + if separateTrie != nil { + snaptree, err = snapshot.New(snapConfig, db, trie.NewDatabase(separateTrie, nil), root, int(triesInMemory), false) + } else { + snaptree, err = snapshot.New(snapConfig, db, trie.NewDatabase(db, nil), root, int(triesInMemory), false) + } +>>>>>>> b5a9db378 (refactor: delete the trie datadir flag and make it fixed) if err != nil { return err } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 544a61c1de..0e5c764531 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -93,11 +93,10 @@ var ( Value: flags.DirectoryString(node.DefaultDataDir()), Category: flags.EthCategory, } - - TrieDirFlag = &flags.DirectoryFlag{ - Name: "triedir", - Usage: "Data directory for the trie data base", - Value: flags.DirectoryString(node.DefaultDataDir() + "trie"), + SeparateDBFlag = &cli.BoolFlag{ + Name: "separatetrie", + Usage: "Enable a separated trie database, it will be created within a subdirectory called state, " + + "Users can copy this state directory to another directory or disk, and then create a symbolic link to the state directory under the chaindata", Category: flags.EthCategory, } DirectBroadcastFlag = &cli.BoolFlag{ @@ -1119,7 +1118,7 @@ var ( DBEngineFlag, StateSchemeFlag, HttpHeaderFlag, - TrieDirFlag, + SeparateDBFlag, } ) @@ -1638,12 +1637,12 @@ func SetDataDir(ctx *cli.Context, cfg *node.Config) { switch { case ctx.IsSet(DataDirFlag.Name): cfg.DataDir = ctx.String(DataDirFlag.Name) - case ctx.IsSet(TrieDirFlag.Name): - fmt.Println("setting TrieDirFlag.Name", ctx.String(TrieDirFlag.Name)) - cfg.TrieDir = ctx.String(TrieDirFlag.Name) case ctx.Bool(DeveloperFlag.Name): cfg.DataDir = "" // unless explicitly requested, use memory databases } + if ctx.IsSet(SeparateDBFlag.Name) { + cfg.EnableSeparateTrie = true + } } func setVoteJournalDir(ctx *cli.Context, cfg *node.Config) { @@ -2143,15 +2142,6 @@ func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) { // RegisterEthService adds an Ethereum client to the stack. // The second return value is the full node instance. func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend, *eth.Ethereum) { - if cfg.SyncMode == downloader.LightSync { - backend, err := les.New(stack, cfg) - if err != nil { - Fatalf("Failed to register the Ethereum service: %v", err) - } - stack.RegisterAPIs(tracers.APIs(backend.ApiBackend)) - return backend.ApiBackend, nil - } - backend, err := eth.New(stack, cfg) if err != nil { Fatalf("Failed to register the Ethereum service: %v", err) @@ -2341,6 +2331,17 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFree return chainDb } +// MakeSeparateTrieDB open a separate trie database using the flags passed to the client and will hard crash if it fails. +func MakeSeparateTrieDB(ctx *cli.Context, stack *node.Node, readonly, disableFreeze bool) ethdb.Database { + cache := ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100 + handles := MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name)) + trieDb, err := stack.OpenTrieDataBase("chaindata", cache, handles, "", readonly, disableFreeze, false, false) + if err != nil { + Fatalf("Failed to open separate trie database: %v", err) + } + return trieDb +} + // tryMakeReadOnlyDatabase try to open the chain database in read-only mode, // or fallback to write mode if the database is not initialized. // diff --git a/core/blockchain.go b/core/blockchain.go index d18387fa6b..0faa5f7465 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -22,6 +22,7 @@ import ( "fmt" "io" "math/big" + "path/filepath" "runtime" "sort" "sync" @@ -165,8 +166,20 @@ type CacheConfig struct { StateScheme string // Scheme used to store ethereum states and merkle tree nodes on top PathSyncFlush bool // Whether sync flush the trienodebuffer of pathdb to disk. - SnapshotNoBuild bool // Whether the background generation is allowed - SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it + SnapshotNoBuild bool // Whether the background generation is allowed + SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it + SeparateTrieConfig *SeparateTrieConfig // The configuration of the separated single trie database +} + +// SeparateTrieConfig contains the configuration values of the separated single trie database +type SeparateTrieConfig struct { + SeparateDBHandles int // The handler num used by the separated trie db + SeparateDBCache int // The cache size used by the separated trie db + SeparateDBEngine string // The db engine (pebble or leveldb) used by the separated trie db + TrieDataDir string // The directory of the separated trie db + TrieNameSpace string // The namespace of the separated trie db + SeparateDBAncient string // The ancient directory of the separated trie db + PruneAncientData bool } // triedbConfig derives the configures for trie database. @@ -240,8 +253,7 @@ type BlockChain struct { chainConfig *params.ChainConfig // Chain & network configuration cacheConfig *CacheConfig // Cache configuration for pruning - db ethdb.Database // Low level persistent database to store final content in - separateDB ethdb.Database + db ethdb.Database // Low level persistent database to store final content in snaps *snapshot.Tree // Snapshot tree for fast trie leaf access triegc *prque.Prque[int64, common.Hash] // Priority queue mapping block numbers to tries to gc gcproc time.Duration // Accumulates canonical block processing for trie dumping @@ -337,10 +349,8 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis */ bc := &BlockChain{ - // chainConfig: chainConfig, - cacheConfig: cacheConfig, - db: db, - // triedb: triedb, + cacheConfig: cacheConfig, + db: db, triegc: prque.New[int64, common.Hash](nil), quit: make(chan struct{}), triesInMemory: cacheConfig.TriesInMemory, @@ -360,19 +370,32 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis diffQueueBuffer: make(chan *types.DiffLayer), } var err error - // do options before start any routine - for _, option := range options { - bc, err = option(bc) - if err != nil { - return nil, err - } - } // Open trie database with provided config var triedb *trie.Database - if bc.separateDB != nil { - log.Info("the separate db of block chain has been set") - triedb = trie.NewDatabase(bc.separateDB, cacheConfig.triedbConfig()) + if cacheConfig.SeparateTrieConfig != nil { + separatedTrieConfig := cacheConfig.SeparateTrieConfig + separatedTrieDir := separatedTrieConfig.TrieDataDir + log.Info("node run with separated trie database", "directory", separatedTrieDir) + // open the separated db to init the trie database which only store the trie data + separateDB, dbErr := rawdb.Open(rawdb.OpenOptions{ + Type: separatedTrieConfig.SeparateDBEngine, + Directory: separatedTrieDir, + AncientsDirectory: filepath.Join(separatedTrieDir, separatedTrieConfig.SeparateDBAncient), + Namespace: separatedTrieConfig.TrieNameSpace, + Cache: separatedTrieConfig.SeparateDBCache, + Handles: separatedTrieConfig.SeparateDBHandles, + ReadOnly: false, + DisableFreeze: false, + IsLastOffset: false, + PruneAncientData: separatedTrieConfig.PruneAncientData, + }) + + if dbErr != nil { + log.Error("Failed to separate trie database", "err", dbErr) + return nil, dbErr + } + triedb = trie.NewDatabase(separateDB, cacheConfig.triedbConfig()) } else { triedb = trie.NewDatabase(db, cacheConfig.triedbConfig()) } @@ -384,9 +407,9 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { return nil, genesisErr } + bc.chainConfig = chainConfig systemcontracts.GenesisHash = genesisHash log.Info("Initialised chain configuration", "config", chainConfig) - bc.chainConfig = chainConfig bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit)) bc.forker = NewForkChoice(bc, shouldPreserve) @@ -542,7 +565,13 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis } bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root, int(bc.cacheConfig.TriesInMemory), bc.NoTries()) } - + // do options before start any routine + for _, option := range options { + bc, err = option(bc) + if err != nil { + return nil, err + } + } // Start future block processor. bc.wg.Add(1) go bc.updateFutureBlocks() @@ -2871,15 +2900,6 @@ func EnablePipelineCommit(bc *BlockChain) (*BlockChain, error) { return bc, nil } -func EnableSeparateDB(separateDB ethdb.Database) BlockChainOption { - return func(chain *BlockChain) (*BlockChain, error) { - if separateDB != nil { - chain.separateDB = separateDB - } - return chain, nil - } -} - func EnablePersistDiff(limit uint64) BlockChainOption { return func(chain *BlockChain) (*BlockChain, error) { chain.diffLayerFreezerBlockLimit = limit diff --git a/core/rawdb/database.go b/core/rawdb/database.go index 7f8608f399..f27d96d13a 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -603,12 +603,31 @@ func PruneHashTrieNodeInDataBase(db ethdb.Database) error { return nil } +func inspectTrieData(key, value []byte, legacyTries, accountTries, storageTries, stateLookups *stat) { + size := common.StorageSize(len(key) + len(value)) + switch { + case IsLegacyTrieNode(key, value): + legacyTries.Add(size) + case bytes.HasPrefix(key, stateIDPrefix) && len(key) == len(stateIDPrefix)+common.HashLength: + stateLookups.Add(size) + case IsAccountTrieNode(key): + accountTries.Add(size) + case IsStorageTrieNode(key): + storageTries.Add(size) + } +} + // InspectDatabase traverses the entire database and checks the size // of all different categories of data. -func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { +func InspectDatabase(db ethdb.Database, separateDB ethdb.Database, keyPrefix, keyStart []byte) error { it := db.NewIterator(keyPrefix, keyStart) defer it.Release() + var trieIter ethdb.Iterator + if separateDB != nil { + trieIter = separateDB.NewIterator(keyPrefix, nil) + defer trieIter.Release() + } var ( count int64 start = time.Now() @@ -728,6 +747,31 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { logged = time.Now() } } + // inspect separate trie db + if trieIter != nil { + count = 0 + logged = time.Now() + for trieIter.Next() { + var ( + key = trieIter.Key() + value = trieIter.Value() + size = common.StorageSize(len(key) + len(value)) + ) + inspectTrieData(key, value, &legacyTries, &accountTries, &storageTries, &stateLookups) + for _, meta := range [][]byte{ + fastTrieProgressKey, persistentStateIDKey, trieJournalKey} { + if bytes.Equal(key, meta) { + metadata.Add(size) + break + } + } + count++ + if count%1000 == 0 && time.Since(logged) > 8*time.Second { + log.Info("Inspecting separate database", "count", count, "elapsed", common.PrettyDuration(time.Since(start))) + logged = time.Now() + } + } + } // Display the database statistic of key-value store. stats := [][]string{ {"Key-Value store", "Headers", headers.Size(), headers.Count()}, @@ -768,6 +812,28 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { } total += ancient.size() } + + // inspect ancient state in separate trie db if exist + if trieIter != nil { + stateAncients, err := inspectFreezers(separateDB) + if err != nil { + return err + } + for _, ancient := range stateAncients { + for _, table := range ancient.sizes { + if ancient.name == "chain" { + break + } + stats = append(stats, []string{ + fmt.Sprintf("Ancient store (%s)", strings.Title(ancient.name)), + strings.Title(table.name), + table.size.String(), + fmt.Sprintf("%d", ancient.count()), + }) + } + total += ancient.size() + } + } table := tablewriter.NewWriter(os.Stdout) table.SetHeader([]string{"Database", "Category", "Size", "Items"}) table.SetFooter([]string{"", "Total", total.String(), " "}) diff --git a/core/state/state_object.go b/core/state/state_object.go index 02e4d5623e..524bdc47cd 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -183,7 +183,6 @@ func (s *stateObject) getOriginStorage(key common.Hash) (common.Hash, bool) { if value, cached := s.originStorage[key]; cached { return value, true } - // if L1 cache miss, try to get it from shared pool if s.sharedOriginStorage != nil { val, ok := s.sharedOriginStorage.Load(key) diff --git a/eth/backend.go b/eth/backend.go index df0aab47bd..ccf6d513e6 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "math/big" + "path/filepath" "runtime" "sync" @@ -67,6 +68,11 @@ import ( "github.com/ethereum/go-ethereum/trie/triedb/pathdb" ) +const ( + SeparateDBNamespace = "eth/separatedb/chaindata/" + SeparateTrieNamespace = "eth/triedb/chaindata/" +) + // Config contains the configuration options of the ETH protocol. // Deprecated: use ethconfig.Config instead. type Config = ethconfig.Config @@ -133,10 +139,22 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { } // Assemble the Ethereum object - chainDb, err := stack.OpenAndMergeDatabase("chaindata", config.DatabaseCache, config.DatabaseHandles, - config.DatabaseFreezer, config.DatabaseDiff, "eth/db/chaindata/", false, config.PersistDiff, config.PruneAncientData) - if err != nil { - return nil, err + var chainDb ethdb.Database + var err error + if stack.Config().EnableSeparateTrie || stack.HasSeparateTrieDir() { + // It is the separated db which contain snapshot, meta and block data with no trie data storing in it. + // Allocate partial handles and cache to this separate database because it is not a complete database. + chainDb, err = stack.OpenAndMergeDatabase("chaindata", int(float64(config.DatabaseCache)*0.6), int(float64(config.DatabaseHandles)*0.6), + config.DatabaseFreezer, config.DatabaseDiff, SeparateDBNamespace, false, config.PersistDiff, config.PruneAncientData) + if err != nil { + return nil, err + } + } else { + chainDb, err = stack.OpenAndMergeDatabase("chaindata", config.DatabaseCache, config.DatabaseHandles, + config.DatabaseFreezer, config.DatabaseDiff, "eth/db/chaindata/", false, config.PersistDiff, config.PruneAncientData) + if err != nil { + return nil, err + } } config.StateScheme, err = rawdb.ParseStateScheme(config.StateScheme, chainDb) if err != nil { @@ -272,19 +290,28 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { bcOps = append(bcOps, core.EnableDoubleSignChecker) } - if stack.Config().TrieDir != "" { - fmt.Println("trie data dir has setted to ", stack.Config().TrieDir) - newChainDb, err := stack.OpenDatabaseForTrie("chaindata", config.DatabaseCache, config.DatabaseHandles, - config.DatabaseFreezer, "eth/db/chaindata/", false, false, false, config.PruneAncientData) - if err != nil { - log.Info("open db err", err) - return nil, err + peers := newPeerSet() + bcOps = append(bcOps, core.EnableBlockValidator(chainConfig, eth.engine, config.TriesVerifyMode, peers)) + + // if the separated trie db has set, need to new blockchain with the separated trie database + if stack.Config().EnableSeparateTrie || stack.HasSeparateTrieDir() { + ancientDir := config.DatabaseFreezer + if ancientDir == "" { + ancientDir = "ancient" + } + // Allocate partial handles and cache to this separated database. + separateDir := filepath.Join(stack.ResolvePath("chaindata"), "state") + separatedDBConfig := &core.SeparateTrieConfig{ + SeparateDBHandles: int(float64(config.DatabaseHandles) * 0.5), + SeparateDBCache: int(float64(config.DatabaseCache) * 0.5), + SeparateDBEngine: stack.Config().DBEngine, + TrieDataDir: separateDir, + TrieNameSpace: SeparateTrieNamespace, + SeparateDBAncient: ancientDir, } - bcOps = append(bcOps, core.EnableSeparateDB(newChainDb)) + cacheConfig.SeparateTrieConfig = separatedDBConfig } - peers := newPeerSet() - bcOps = append(bcOps, core.EnableBlockValidator(chainConfig, eth.engine, config.TriesVerifyMode, peers)) eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, eth.shouldPreserve, &config.TransactionHistory, bcOps...) if err != nil { return nil, err diff --git a/miner/stress/clique/main.go b/miner/stress/clique/main.go index 2f11b4aa97..55eb3f2161 100644 --- a/miner/stress/clique/main.go +++ b/miner/stress/clique/main.go @@ -183,7 +183,6 @@ func makeGenesis(faucets []*ecdsa.PrivateKey, sealers []*ecdsa.PrivateKey) *core func makeSealer(genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) { // Define the basic configurations for the Ethereum node datadir, _ := os.MkdirTemp("", "") - log.Info("making sealer") config := &node.Config{ Name: "geth", Version: params.Version, diff --git a/node/config.go b/node/config.go index 16c01fdad7..be75dd50da 100644 --- a/node/config.go +++ b/node/config.go @@ -64,8 +64,8 @@ type Config struct { // in memory. DataDir string - // TrieDir is the file system folder the node should use for storing trie data. - TrieDir string + // EnableSeparateTrie is a flag that whether to enable the separated single trie database + EnableSeparateTrie bool `toml:",omitempty"` // Configuration of peer-to-peer networking. P2P p2p.Config @@ -396,13 +396,6 @@ func (c *Config) instanceDir() string { return filepath.Join(c.DataDir, c.name()) } -func (c *Config) trieDir() string { - if c.TrieDir == "" { - return "" - } - return filepath.Join(c.TrieDir, c.name()) -} - // NodeKey retrieves the currently configured private key of the node, checking // first any manually set key, falling back to the one found in the configured // data folder. If no key can be found, a new one is generated. @@ -448,8 +441,8 @@ func (c *Config) checkLegacyFiles() { c.checkLegacyFile(c.ResolvePath(datadirTrustedNodes)) } -func (c *Config) enableSeparateTrie(trieDir string) { - c.TrieDir = trieDir +func (c *Config) enableSeparateTrie() { + c.EnableSeparateTrie = true } // checkLegacyFile will only raise an error if a file at the given path exists. diff --git a/node/node.go b/node/node.go index 220836348a..987c7fb863 100644 --- a/node/node.go +++ b/node/node.go @@ -180,8 +180,8 @@ func New(conf *Config) (*Node, error) { node.server.Config.NodeDatabase = node.config.NodeDB() } - if conf.TrieDir != "" { - node.config.enableSeparateTrie(conf.TrieDir) + if conf.EnableSeparateTrie { + node.config.enableSeparateTrie() } // Check HTTP/WS prefixes are valid. @@ -840,7 +840,10 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient, return db, err } -func (n *Node) OpenDatabaseForTrie(name string, cache, handles int, ancient, namespace string, readonly, disableFreeze, isLastOffset, pruneAncientData bool) (ethdb.Database, error) { +// OpenTrieDataBase opens an existing database to store the trie data with the given name (or +// creates one if no previous can be found) from within the node's data directory. +// This function is only used in scenarios where the separate db is used. +func (n *Node) OpenTrieDataBase(name string, cache, handles int, namespace string, readonly, disableFreeze, isLastOffset, pruneAncientData bool) (ethdb.Database, error) { n.lock.Lock() defer n.lock.Unlock() if n.state == closedState { @@ -848,23 +851,19 @@ func (n *Node) OpenDatabaseForTrie(name string, cache, handles int, ancient, nam } var db ethdb.Database var err error - if n.config.DataDir == "" { - db = rawdb.NewMemoryDatabase() - } else { - direcrory := filepath.Join(n.config.trieDir(), name) - db, err = rawdb.Open(rawdb.OpenOptions{ - Type: n.config.DBEngine, - Directory: direcrory, - AncientsDirectory: filepath.Join(direcrory, "ancient"), - Namespace: namespace, - Cache: cache, - Handles: handles, - ReadOnly: readonly, - DisableFreeze: disableFreeze, - IsLastOffset: isLastOffset, - PruneAncientData: pruneAncientData, - }) - } + separateDir := filepath.Join(n.ResolvePath(name), "state") + db, err = rawdb.Open(rawdb.OpenOptions{ + Type: n.config.DBEngine, + Directory: separateDir, + AncientsDirectory: filepath.Join(separateDir, "ancient"), + Namespace: namespace, + Cache: cache, + Handles: handles, + ReadOnly: readonly, + DisableFreeze: disableFreeze, + IsLastOffset: isLastOffset, + PruneAncientData: pruneAncientData, + }) if err == nil { db = n.wrapDatabase(db) @@ -872,6 +871,16 @@ func (n *Node) OpenDatabaseForTrie(name string, cache, handles int, ancient, nam return db, err } +// HasSeparateTrieDir check the state subdirectory of db, if subdirectory exists, return true +func (n *Node) HasSeparateTrieDir() bool { + separateDir := filepath.Join(n.ResolvePath("chaindata"), "state") + fileInfo, err := os.Stat(separateDir) + if os.IsNotExist(err) { + return false + } + return fileInfo.IsDir() +} + func (n *Node) OpenDiffDatabase(name string, handles int, diff, namespace string, readonly bool) (*leveldb.Database, error) { n.lock.Lock() defer n.lock.Unlock() From 3b242e435d7e50b63dd6fee77e519cfc5da6bb2a Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Thu, 1 Feb 2024 20:48:24 +0800 Subject: [PATCH 06/18] fix: fix db compaction --- cmd/geth/dbcmd.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index 40a7363798..20fefa47e7 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -609,9 +609,11 @@ func dbCompact(ctx *cli.Context) error { return err } - if err := separateTrieDB.Compact(nil, nil); err != nil { - log.Error("Compact err", "error", err) - return err + if separateTrieDB != nil { + if err := separateTrieDB.Compact(nil, nil); err != nil { + log.Error("Compact err", "error", err) + return err + } } log.Info("Stats after compaction") From 64029de12697bb77361406fd29a6e11f9d84633d Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Fri, 2 Feb 2024 13:07:00 +0800 Subject: [PATCH 07/18] fix:optimize variable names --- cmd/geth/chaincmd.go | 8 +++---- cmd/geth/dbcmd.go | 54 ++++++++++++++++++++++---------------------- cmd/geth/snapshot.go | 32 -------------------------- cmd/utils/flags.go | 12 +++++----- core/blockchain.go | 44 ++++++++++++++++++------------------ eth/backend.go | 18 +++++++-------- node/node.go | 4 ++-- 7 files changed, 70 insertions(+), 102 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 8d00beb778..3ad0dc0928 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -239,14 +239,14 @@ func initGenesis(ctx *cli.Context) error { var triedb *trie.Database // if the trie data dir has been set , new trie db with a new trie database - if ctx.IsSet(utils.SeparateDBFlag.Name) { - separatedDB, dbErr := stack.OpenTrieDataBase(name, 0, 0, "", false, false, false, false) + if ctx.IsSet(utils.SeparateTrieFlag.Name) { + statediskdb, dbErr := stack.OpenStateDataBase(name, 0, 0, "", false, false, false, false) if dbErr != nil { utils.Fatalf("Failed to open separate trie database: %v", dbErr) } - defer separatedDB.Close() + defer statediskdb.Close() - triedb = utils.MakeTrieDatabase(ctx, separatedDB, ctx.Bool(utils.CachePreimagesFlag.Name), false) + triedb = utils.MakeTrieDatabase(ctx, statediskdb, ctx.Bool(utils.CachePreimagesFlag.Name), false) defer triedb.Close() } else { triedb = utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false) diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index 20fefa47e7..5a2721c973 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -381,10 +381,10 @@ func inspectTrie(ctx *cli.Context) error { db := utils.MakeChainDatabase(ctx, stack, true, false) defer db.Close() - var separateTrie ethdb.Database + var statediskdb ethdb.Database if stack.HasSeparateTrieDir() { - separateTrie = utils.MakeSeparateTrieDB(ctx, stack, true, false) - defer separateTrie.Close() + statediskdb = utils.MakeStateDataBase(ctx, stack, true, false) + defer statediskdb.Close() } var headerBlockHash common.Hash if ctx.NArg() >= 1 { @@ -436,8 +436,8 @@ func inspectTrie(ctx *cli.Context) error { } var triedb *trie.Database - if separateTrie != nil { - triedb = trie.NewDatabase(separateTrie, config) + if statediskdb != nil { + triedb = trie.NewDatabase(statediskdb, config) } else { triedb = trie.NewDatabase(db, config) } @@ -484,12 +484,12 @@ func inspect(ctx *cli.Context) error { db := utils.MakeChainDatabase(ctx, stack, true, false) defer db.Close() - var seprateDB ethdb.Database + var statediskdb ethdb.Database if stack.HasSeparateTrieDir() { - seprateDB = utils.MakeSeparateTrieDB(ctx, stack, true, false) - defer seprateDB.Close() + statediskdb = utils.MakeStateDataBase(ctx, stack, true, false) + defer statediskdb.Close() } - return rawdb.InspectDatabase(db, seprateDB, prefix, start) + return rawdb.InspectDatabase(db, statediskdb, prefix, start) } func ancientInspect(ctx *cli.Context) error { @@ -577,10 +577,10 @@ func dbStats(ctx *cli.Context) error { showLeveldbStats(db) if stack.HasSeparateTrieDir() { - seprateTrieDB := utils.MakeSeparateTrieDB(ctx, stack, true, false) - defer seprateTrieDB.Close() + statediskdb := utils.MakeStateDataBase(ctx, stack, true, false) + defer statediskdb.Close() fmt.Println("show stats of separated db") - showLeveldbStats(seprateTrieDB) + showLeveldbStats(statediskdb) } return nil @@ -596,11 +596,11 @@ func dbCompact(ctx *cli.Context) error { log.Info("Stats before compaction") showLeveldbStats(db) - var separateTrieDB ethdb.Database + var statediskdb ethdb.Database if stack.HasSeparateTrieDir() { - separateTrieDB = utils.MakeSeparateTrieDB(ctx, stack, false, false) - defer separateTrieDB.Close() - showLeveldbStats(separateTrieDB) + statediskdb = utils.MakeStateDataBase(ctx, stack, false, false) + defer statediskdb.Close() + showLeveldbStats(statediskdb) } log.Info("Triggering compaction") @@ -609,8 +609,8 @@ func dbCompact(ctx *cli.Context) error { return err } - if separateTrieDB != nil { - if err := separateTrieDB.Compact(nil, nil); err != nil { + if statediskdb != nil { + if err := statediskdb.Compact(nil, nil); err != nil { log.Error("Compact err", "error", err) return err } @@ -618,8 +618,8 @@ func dbCompact(ctx *cli.Context) error { log.Info("Stats after compaction") showLeveldbStats(db) - if separateTrieDB != nil { - showLeveldbStats(separateTrieDB) + if statediskdb != nil { + showLeveldbStats(statediskdb) } return nil } @@ -645,11 +645,11 @@ func dbGet(ctx *cli.Context) error { if err != nil { // if separate trie db exist, try to get it from separate db if stack.HasSeparateTrieDir() { - trieDB := utils.MakeSeparateTrieDB(ctx, stack, true, false) - defer trieDB.Close() - triedata, dberr := trieDB.Get(key) + statediskdb := utils.MakeStateDataBase(ctx, stack, true, false) + defer statediskdb.Close() + statedata, dberr := statediskdb.Get(key) if dberr == nil { - fmt.Printf("key %#x: %#x\n", key, triedata) + fmt.Printf("key %#x: %#x\n", key, statedata) return nil } } @@ -670,7 +670,7 @@ func dbTrieGet(ctx *cli.Context) error { var db ethdb.Database if stack.HasSeparateTrieDir() { - db = utils.MakeSeparateTrieDB(ctx, stack, true, false) + db = utils.MakeStateDataBase(ctx, stack, true, false) } else { db = utils.MakeChainDatabase(ctx, stack, true, false) } @@ -741,7 +741,7 @@ func dbTrieDelete(ctx *cli.Context) error { var db ethdb.Database if stack.HasSeparateTrieDir() { - db = utils.MakeSeparateTrieDB(ctx, stack, true, false) + db = utils.MakeStateDataBase(ctx, stack, true, false) } else { db = utils.MakeChainDatabase(ctx, stack, true, false) } @@ -868,7 +868,7 @@ func dbDumpTrie(ctx *cli.Context) error { var db ethdb.Database if stack.HasSeparateTrieDir() { - db = utils.MakeSeparateTrieDB(ctx, stack, true, false) + db = utils.MakeStateDataBase(ctx, stack, true, false) } else { db = utils.MakeChainDatabase(ctx, stack, true, false) } diff --git a/cmd/geth/snapshot.go b/cmd/geth/snapshot.go index 97363237b0..73453c0f91 100644 --- a/cmd/geth/snapshot.go +++ b/cmd/geth/snapshot.go @@ -685,18 +685,7 @@ func traverseRawState(ctx *cli.Context) error { chaindb := utils.MakeChainDatabase(ctx, stack, true, false) defer chaindb.Close() -<<<<<<< HEAD triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false) -======= - var triedb *trie.Database - if stack.HasSeparateTrieDir() { - separateTrie := utils.MakeSeparateTrieDB(ctx, stack, true, false) - defer separateTrie.Close() - triedb = utils.MakeTrieDatabase(ctx, separateTrie, false, true) - } else { - triedb = utils.MakeTrieDatabase(ctx, chaindb, false, true) - } ->>>>>>> b5a9db378 (refactor: delete the trie datadir flag and make it fixed) defer triedb.Close() headBlock := rawdb.ReadHeadBlock(chaindb) @@ -860,18 +849,7 @@ func dumpState(ctx *cli.Context) error { if err != nil { return err } -<<<<<<< HEAD triedb := utils.MakeTrieDatabase(ctx, db, false, true, false) -======= - - var separateTrie ethdb.Database - if stack.HasSeparateTrieDir() { - separateTrie = utils.MakeSeparateTrieDB(ctx, stack, true, false) - defer separateTrie.Close() - } - - triedb := utils.MakeTrieDatabase(ctx, db, false, true) ->>>>>>> b5a9db378 (refactor: delete the trie datadir flag and make it fixed) defer triedb.Close() snapConfig := snapshot.Config{ @@ -881,17 +859,7 @@ func dumpState(ctx *cli.Context) error { AsyncBuild: false, } triesInMemory := ctx.Uint64(utils.TriesInMemoryFlag.Name) -<<<<<<< HEAD snaptree, err := snapshot.New(snapConfig, db, triedb, root, int(triesInMemory), false) -======= - - var snaptree *snapshot.Tree - if separateTrie != nil { - snaptree, err = snapshot.New(snapConfig, db, trie.NewDatabase(separateTrie, nil), root, int(triesInMemory), false) - } else { - snaptree, err = snapshot.New(snapConfig, db, trie.NewDatabase(db, nil), root, int(triesInMemory), false) - } ->>>>>>> b5a9db378 (refactor: delete the trie datadir flag and make it fixed) if err != nil { return err } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 0e5c764531..543c327427 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -93,7 +93,7 @@ var ( Value: flags.DirectoryString(node.DefaultDataDir()), Category: flags.EthCategory, } - SeparateDBFlag = &cli.BoolFlag{ + SeparateTrieFlag = &cli.BoolFlag{ Name: "separatetrie", Usage: "Enable a separated trie database, it will be created within a subdirectory called state, " + "Users can copy this state directory to another directory or disk, and then create a symbolic link to the state directory under the chaindata", @@ -1118,7 +1118,7 @@ var ( DBEngineFlag, StateSchemeFlag, HttpHeaderFlag, - SeparateDBFlag, + SeparateTrieFlag, } ) @@ -1640,7 +1640,7 @@ func SetDataDir(ctx *cli.Context, cfg *node.Config) { case ctx.Bool(DeveloperFlag.Name): cfg.DataDir = "" // unless explicitly requested, use memory databases } - if ctx.IsSet(SeparateDBFlag.Name) { + if ctx.IsSet(SeparateTrieFlag.Name) { cfg.EnableSeparateTrie = true } } @@ -2331,11 +2331,11 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFree return chainDb } -// MakeSeparateTrieDB open a separate trie database using the flags passed to the client and will hard crash if it fails. -func MakeSeparateTrieDB(ctx *cli.Context, stack *node.Node, readonly, disableFreeze bool) ethdb.Database { +// MakeStateDataBase open a separate trie database using the flags passed to the client and will hard crash if it fails. +func MakeStateDataBase(ctx *cli.Context, stack *node.Node, readonly, disableFreeze bool) ethdb.Database { cache := ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100 handles := MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name)) - trieDb, err := stack.OpenTrieDataBase("chaindata", cache, handles, "", readonly, disableFreeze, false, false) + trieDb, err := stack.OpenStateDataBase("chaindata", cache, handles, "", readonly, disableFreeze, false, false) if err != nil { Fatalf("Failed to open separate trie database: %v", err) } diff --git a/core/blockchain.go b/core/blockchain.go index 0faa5f7465..db1882405e 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -166,20 +166,20 @@ type CacheConfig struct { StateScheme string // Scheme used to store ethereum states and merkle tree nodes on top PathSyncFlush bool // Whether sync flush the trienodebuffer of pathdb to disk. - SnapshotNoBuild bool // Whether the background generation is allowed - SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it - SeparateTrieConfig *SeparateTrieConfig // The configuration of the separated single trie database + SnapshotNoBuild bool // Whether the background generation is allowed + SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it + StateDiskDBConfig *StateDatabaseConfig // The configuration of the separated single trie database } -// SeparateTrieConfig contains the configuration values of the separated single trie database -type SeparateTrieConfig struct { - SeparateDBHandles int // The handler num used by the separated trie db - SeparateDBCache int // The cache size used by the separated trie db - SeparateDBEngine string // The db engine (pebble or leveldb) used by the separated trie db - TrieDataDir string // The directory of the separated trie db - TrieNameSpace string // The namespace of the separated trie db - SeparateDBAncient string // The ancient directory of the separated trie db - PruneAncientData bool +// StateDatabaseConfig contains the configuration values of the separated single state database +type StateDatabaseConfig struct { + StateHandles int // The handler num used by the separated state db + StateCache int // The cache size used by the separated state db + StateEngine string // The db engine (pebble or leveldb) used by the separated state db + StateDataDir string // The directory of the separated state db + NameSpace string // The namespace of the separated state db + StateAncient string // The ancient directory of the separated state db + PruneAncientData bool } // triedbConfig derives the configures for trie database. @@ -373,18 +373,18 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis // Open trie database with provided config var triedb *trie.Database - if cacheConfig.SeparateTrieConfig != nil { - separatedTrieConfig := cacheConfig.SeparateTrieConfig - separatedTrieDir := separatedTrieConfig.TrieDataDir + if cacheConfig.StateDiskDBConfig != nil { + separatedTrieConfig := cacheConfig.StateDiskDBConfig + separatedTrieDir := separatedTrieConfig.StateDataDir log.Info("node run with separated trie database", "directory", separatedTrieDir) // open the separated db to init the trie database which only store the trie data - separateDB, dbErr := rawdb.Open(rawdb.OpenOptions{ - Type: separatedTrieConfig.SeparateDBEngine, + statediskdb, dbErr := rawdb.Open(rawdb.OpenOptions{ + Type: separatedTrieConfig.StateEngine, Directory: separatedTrieDir, - AncientsDirectory: filepath.Join(separatedTrieDir, separatedTrieConfig.SeparateDBAncient), - Namespace: separatedTrieConfig.TrieNameSpace, - Cache: separatedTrieConfig.SeparateDBCache, - Handles: separatedTrieConfig.SeparateDBHandles, + AncientsDirectory: filepath.Join(separatedTrieDir, separatedTrieConfig.StateAncient), + Namespace: separatedTrieConfig.NameSpace, + Cache: separatedTrieConfig.StateCache, + Handles: separatedTrieConfig.StateHandles, ReadOnly: false, DisableFreeze: false, IsLastOffset: false, @@ -395,7 +395,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis log.Error("Failed to separate trie database", "err", dbErr) return nil, dbErr } - triedb = trie.NewDatabase(separateDB, cacheConfig.triedbConfig()) + triedb = trie.NewDatabase(statediskdb, cacheConfig.triedbConfig()) } else { triedb = trie.NewDatabase(db, cacheConfig.triedbConfig()) } diff --git a/eth/backend.go b/eth/backend.go index ccf6d513e6..2061f59283 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -300,16 +300,16 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { ancientDir = "ancient" } // Allocate partial handles and cache to this separated database. - separateDir := filepath.Join(stack.ResolvePath("chaindata"), "state") - separatedDBConfig := &core.SeparateTrieConfig{ - SeparateDBHandles: int(float64(config.DatabaseHandles) * 0.5), - SeparateDBCache: int(float64(config.DatabaseCache) * 0.5), - SeparateDBEngine: stack.Config().DBEngine, - TrieDataDir: separateDir, - TrieNameSpace: SeparateTrieNamespace, - SeparateDBAncient: ancientDir, + stateDirectory := filepath.Join(stack.ResolvePath("chaindata"), "state") + stateDBConfig := &core.StateDatabaseConfig{ + StateHandles: int(float64(config.DatabaseHandles) * 0.5), + StateCache: int(float64(config.DatabaseCache) * 0.5), + StateEngine: stack.Config().DBEngine, + StateDataDir: stateDirectory, + NameSpace: SeparateTrieNamespace, + StateAncient: ancientDir, } - cacheConfig.SeparateTrieConfig = separatedDBConfig + cacheConfig.StateDiskDBConfig = stateDBConfig } eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, eth.shouldPreserve, &config.TransactionHistory, bcOps...) diff --git a/node/node.go b/node/node.go index 987c7fb863..e60c3145de 100644 --- a/node/node.go +++ b/node/node.go @@ -840,10 +840,10 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient, return db, err } -// OpenTrieDataBase opens an existing database to store the trie data with the given name (or +// OpenStateDataBase opens an existing database to store the trie data with the given name (or // creates one if no previous can be found) from within the node's data directory. // This function is only used in scenarios where the separate db is used. -func (n *Node) OpenTrieDataBase(name string, cache, handles int, namespace string, readonly, disableFreeze, isLastOffset, pruneAncientData bool) (ethdb.Database, error) { +func (n *Node) OpenStateDataBase(name string, cache, handles int, namespace string, readonly, disableFreeze, isLastOffset, pruneAncientData bool) (ethdb.Database, error) { n.lock.Lock() defer n.lock.Unlock() if n.state == closedState { From 480be65231675be033effae5386a729a4de747f0 Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Fri, 2 Feb 2024 16:18:27 +0800 Subject: [PATCH 08/18] fix:fix separatedb namespace --- cmd/utils/flags.go | 4 +++- eth/backend.go | 10 +++++----- node/errors.go | 9 +++++---- node/node.go | 3 +++ 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 543c327427..93db325f1e 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -2331,7 +2331,7 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFree return chainDb } -// MakeStateDataBase open a separate trie database using the flags passed to the client and will hard crash if it fails. +// MakeStateDataBase open a separate state database using the flags passed to the client and will hard crash if it fails. func MakeStateDataBase(ctx *cli.Context, stack *node.Node, readonly, disableFreeze bool) ethdb.Database { cache := ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100 handles := MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name)) @@ -2424,6 +2424,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh if err != nil { Fatalf("%v", err) } + cache := &core.CacheConfig{ TrieCleanLimit: ethconfig.Defaults.TrieCleanCache, TrieCleanNoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name), @@ -2436,6 +2437,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh StateScheme: scheme, StateHistory: ctx.Uint64(StateHistoryFlag.Name), } + if cache.TrieDirtyDisabled && !cache.Preimages { cache.Preimages = true log.Info("Enabling recording of key preimages since archive mode is used") diff --git a/eth/backend.go b/eth/backend.go index 2061f59283..86ccf2475c 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -69,8 +69,8 @@ import ( ) const ( - SeparateDBNamespace = "eth/separatedb/chaindata/" - SeparateTrieNamespace = "eth/triedb/chaindata/" + ChainDBNamespace = "eth/db/chaindata/" + StateDBNamespace = "eth/db/statedata/" ) // Config contains the configuration options of the ETH protocol. @@ -145,13 +145,13 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { // It is the separated db which contain snapshot, meta and block data with no trie data storing in it. // Allocate partial handles and cache to this separate database because it is not a complete database. chainDb, err = stack.OpenAndMergeDatabase("chaindata", int(float64(config.DatabaseCache)*0.6), int(float64(config.DatabaseHandles)*0.6), - config.DatabaseFreezer, config.DatabaseDiff, SeparateDBNamespace, false, config.PersistDiff, config.PruneAncientData) + config.DatabaseFreezer, config.DatabaseDiff, ChainDBNamespace, false, config.PersistDiff, config.PruneAncientData) if err != nil { return nil, err } } else { chainDb, err = stack.OpenAndMergeDatabase("chaindata", config.DatabaseCache, config.DatabaseHandles, - config.DatabaseFreezer, config.DatabaseDiff, "eth/db/chaindata/", false, config.PersistDiff, config.PruneAncientData) + config.DatabaseFreezer, config.DatabaseDiff, ChainDBNamespace, false, config.PersistDiff, config.PruneAncientData) if err != nil { return nil, err } @@ -306,7 +306,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { StateCache: int(float64(config.DatabaseCache) * 0.5), StateEngine: stack.Config().DBEngine, StateDataDir: stateDirectory, - NameSpace: SeparateTrieNamespace, + NameSpace: StateDBNamespace, StateAncient: ancientDir, } cacheConfig.StateDiskDBConfig = stateDBConfig diff --git a/node/errors.go b/node/errors.go index 67547bf691..e7f60ce9bc 100644 --- a/node/errors.go +++ b/node/errors.go @@ -24,10 +24,11 @@ import ( ) var ( - ErrDatadirUsed = errors.New("datadir already used by another process") - ErrNodeStopped = errors.New("node not started") - ErrNodeRunning = errors.New("node already running") - ErrServiceUnknown = errors.New("unknown service") + ErrDatadirUsed = errors.New("datadir already used by another process") + ErrNodeStopped = errors.New("node not started") + ErrNodeRunning = errors.New("node already running") + ErrServiceUnknown = errors.New("unknown service") + ErrSeprateDBDatadir = errors.New("datadir is not configured when using separate trie") datadirInUseErrnos = map[uint]bool{11: true, 32: true, 35: true} ) diff --git a/node/node.go b/node/node.go index e60c3145de..2e2c3cfc76 100644 --- a/node/node.go +++ b/node/node.go @@ -849,6 +849,9 @@ func (n *Node) OpenStateDataBase(name string, cache, handles int, namespace stri if n.state == closedState { return nil, ErrNodeStopped } + if n.config.DataDir == "" { + return nil, ErrSeprateDBDatadir + } var db ethdb.Database var err error separateDir := filepath.Join(n.ResolvePath(name), "state") From d7d9c001c0f46bd8a6e8958fc74d870e18bccd69 Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Fri, 2 Feb 2024 17:14:18 +0800 Subject: [PATCH 09/18] fix:remove OpenStateDataBase function --- cmd/geth/chaincmd.go | 6 ++--- cmd/utils/flags.go | 6 ++--- core/state/pruner/pruner.go | 2 +- node/node.go | 54 +++++++++++-------------------------- 4 files changed, 23 insertions(+), 45 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 3ad0dc0928..0e08f8fdd1 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -231,16 +231,16 @@ func initGenesis(ctx *cli.Context) error { overrides.OverrideVerkle = &v } for _, name := range []string{"chaindata", "lightchaindata"} { - chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.String(utils.AncientFlag.Name), "", false, false, false, false) + chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.String(utils.AncientFlag.Name), "", false, false, false, false, false) if err != nil { utils.Fatalf("Failed to open database: %v", err) } defer chaindb.Close() var triedb *trie.Database - // if the trie data dir has been set , new trie db with a new trie database + // if the trie data dir has been set, new trie db with a new state database if ctx.IsSet(utils.SeparateTrieFlag.Name) { - statediskdb, dbErr := stack.OpenStateDataBase(name, 0, 0, "", false, false, false, false) + statediskdb, dbErr := stack.OpenDatabaseWithFreezer(name, 0, 0, "", "", false, false, false, false, true) if dbErr != nil { utils.Fatalf("Failed to open separate trie database: %v", dbErr) } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 93db325f1e..f8bb9810fc 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -2323,7 +2323,7 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFree case ctx.String(SyncModeFlag.Name) == "light": chainDb, err = stack.OpenDatabase("lightchaindata", cache, handles, "", readonly) default: - chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly, disableFreeze, false, false) + chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly, disableFreeze, false, false, false) } if err != nil { Fatalf("Could not open database: %v", err) @@ -2335,11 +2335,11 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFree func MakeStateDataBase(ctx *cli.Context, stack *node.Node, readonly, disableFreeze bool) ethdb.Database { cache := ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100 handles := MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name)) - trieDb, err := stack.OpenStateDataBase("chaindata", cache, handles, "", readonly, disableFreeze, false, false) + statediskdb, err := stack.OpenDatabaseWithFreezer("chaindata", cache, handles, "", "", readonly, disableFreeze, false, false, true) if err != nil { Fatalf("Failed to open separate trie database: %v", err) } - return trieDb + return statediskdb } // tryMakeReadOnlyDatabase try to open the chain database in read-only mode, diff --git a/core/state/pruner/pruner.go b/core/state/pruner/pruner.go index 3ba90f73de..396c51dff1 100644 --- a/core/state/pruner/pruner.go +++ b/core/state/pruner/pruner.go @@ -360,7 +360,7 @@ func prune(snaptree *snapshot.Tree, root common.Hash, maindb ethdb.Database, sta func (p *BlockPruner) backUpOldDb(name string, cache, handles int, namespace string, readonly, interrupt bool) error { // Open old db wrapper. - chainDb, err := p.node.OpenDatabaseWithFreezer(name, cache, handles, p.oldAncientPath, namespace, readonly, true, interrupt, false) + chainDb, err := p.node.OpenDatabaseWithFreezer(name, cache, handles, p.oldAncientPath, namespace, readonly, true, interrupt, false, false) if err != nil { log.Error("Failed to open ancient database", "err=", err) return err diff --git a/node/node.go b/node/node.go index 2e2c3cfc76..9ee26d14dc 100644 --- a/node/node.go +++ b/node/node.go @@ -789,7 +789,7 @@ func (n *Node) OpenAndMergeDatabase(name string, cache, handles int, freezer, di if persistDiff { chainDataHandles = handles * chainDataHandlesPercentage / 100 } - chainDB, err := n.OpenDatabaseWithFreezer(name, cache, chainDataHandles, freezer, namespace, readonly, false, false, pruneAncientData) + chainDB, err := n.OpenDatabaseWithFreezer(name, cache, chainDataHandles, freezer, namespace, readonly, false, false, pruneAncientData, false) if err != nil { return nil, err } @@ -809,7 +809,7 @@ func (n *Node) OpenAndMergeDatabase(name string, cache, handles int, freezer, di // also attaching a chain freezer to it that moves ancient chain data from the // database to immutable append-only files. If the node is an ephemeral one, a // memory database is returned. -func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient, namespace string, readonly, disableFreeze, isLastOffset, pruneAncientData bool) (ethdb.Database, error) { +func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient, namespace string, readonly, disableFreeze, isLastOffset, pruneAncientData, isSeparateStateDB bool) (ethdb.Database, error) { n.lock.Lock() defer n.lock.Unlock() if n.state == closedState { @@ -818,12 +818,24 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient, var db ethdb.Database var err error if n.config.DataDir == "" { + if isSeparateStateDB { + return nil, ErrSeprateDBDatadir + } db = rawdb.NewMemoryDatabase() } else { + var dirName, ancientDirName string + if isSeparateStateDB { + // set the directory name as state when opening a separate database, + 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: n.ResolvePath(name), - AncientsDirectory: n.ResolveAncient(name, ancient), + Directory: dirName, + AncientsDirectory: ancientDirName, Namespace: namespace, Cache: cache, Handles: handles, @@ -840,40 +852,6 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient, return db, err } -// OpenStateDataBase opens an existing database to store the trie data with the given name (or -// creates one if no previous can be found) from within the node's data directory. -// This function is only used in scenarios where the separate db is used. -func (n *Node) OpenStateDataBase(name string, cache, handles int, namespace string, readonly, disableFreeze, isLastOffset, pruneAncientData bool) (ethdb.Database, error) { - n.lock.Lock() - defer n.lock.Unlock() - if n.state == closedState { - return nil, ErrNodeStopped - } - if n.config.DataDir == "" { - return nil, ErrSeprateDBDatadir - } - var db ethdb.Database - var err error - separateDir := filepath.Join(n.ResolvePath(name), "state") - db, err = rawdb.Open(rawdb.OpenOptions{ - Type: n.config.DBEngine, - Directory: separateDir, - AncientsDirectory: filepath.Join(separateDir, "ancient"), - Namespace: namespace, - Cache: cache, - Handles: handles, - ReadOnly: readonly, - DisableFreeze: disableFreeze, - IsLastOffset: isLastOffset, - PruneAncientData: pruneAncientData, - }) - - if err == nil { - db = n.wrapDatabase(db) - } - return db, err -} - // HasSeparateTrieDir check the state subdirectory of db, if subdirectory exists, return true func (n *Node) HasSeparateTrieDir() bool { separateDir := filepath.Join(n.ResolvePath("chaindata"), "state") From dd8ec3e176a2f7e83ff5be78f22bf340768f532a Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Mon, 19 Feb 2024 12:32:40 +0800 Subject: [PATCH 10/18] refactor: add stateStore to ethdb database --- cmd/geth/chaincmd.go | 12 ++++------- core/blockchain.go | 29 +------------------------ core/rawdb/accessors_trie.go | 29 ++++++++++++++++++++++++- core/rawdb/database.go | 30 ++++++++++++++++++++++++-- core/rawdb/table.go | 8 +++++++ eth/backend.go | 42 +++++------------------------------- ethdb/database.go | 6 ++++++ ethdb/remotedb/remotedb.go | 8 +++++++ node/node.go | 21 +++++++++++++++++- trie/database.go | 27 +++++++++++++++-------- 10 files changed, 126 insertions(+), 86 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 0e08f8fdd1..5361bc7087 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -237,22 +237,18 @@ func initGenesis(ctx *cli.Context) error { } defer chaindb.Close() - var triedb *trie.Database // if the trie data dir has been set, new trie db with a new state database if ctx.IsSet(utils.SeparateTrieFlag.Name) { statediskdb, dbErr := stack.OpenDatabaseWithFreezer(name, 0, 0, "", "", false, false, false, false, true) if dbErr != nil { utils.Fatalf("Failed to open separate trie database: %v", dbErr) } - defer statediskdb.Close() - - triedb = utils.MakeTrieDatabase(ctx, statediskdb, ctx.Bool(utils.CachePreimagesFlag.Name), false) - defer triedb.Close() - } else { - triedb = utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false) - defer triedb.Close() + chaindb.SetStateStore(statediskdb) } + triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle()) + defer triedb.Close() + _, hash, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides) if err != nil { utils.Fatalf("Failed to write genesis block: %v", err) diff --git a/core/blockchain.go b/core/blockchain.go index db1882405e..dcc8ec65fa 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -22,7 +22,6 @@ import ( "fmt" "io" "math/big" - "path/filepath" "runtime" "sort" "sync" @@ -372,33 +371,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis var err error // Open trie database with provided config - var triedb *trie.Database - if cacheConfig.StateDiskDBConfig != nil { - separatedTrieConfig := cacheConfig.StateDiskDBConfig - separatedTrieDir := separatedTrieConfig.StateDataDir - log.Info("node run with separated trie database", "directory", separatedTrieDir) - // open the separated db to init the trie database which only store the trie data - statediskdb, dbErr := rawdb.Open(rawdb.OpenOptions{ - Type: separatedTrieConfig.StateEngine, - Directory: separatedTrieDir, - AncientsDirectory: filepath.Join(separatedTrieDir, separatedTrieConfig.StateAncient), - Namespace: separatedTrieConfig.NameSpace, - Cache: separatedTrieConfig.StateCache, - Handles: separatedTrieConfig.StateHandles, - ReadOnly: false, - DisableFreeze: false, - IsLastOffset: false, - PruneAncientData: separatedTrieConfig.PruneAncientData, - }) - - if dbErr != nil { - log.Error("Failed to separate trie database", "err", dbErr) - return nil, dbErr - } - triedb = trie.NewDatabase(statediskdb, cacheConfig.triedbConfig()) - } else { - triedb = trie.NewDatabase(db, cacheConfig.triedbConfig()) - } + triedb := trie.NewDatabase(db, cacheConfig.triedbConfig()) bc.triedb = triedb // Setup the genesis block, commit the provided genesis specification // to database if the genesis block is not present yet, or load the diff --git a/core/rawdb/accessors_trie.go b/core/rawdb/accessors_trie.go index 215d63bebb..f4a0adc16b 100644 --- a/core/rawdb/accessors_trie.go +++ b/core/rawdb/accessors_trie.go @@ -311,6 +311,28 @@ func ReadStateScheme(db ethdb.Reader) string { 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) + if len(blob) == 0 { + return "" // no state in disk + } + return HashScheme +} + // ValidateStateScheme used to check state scheme whether is valid. // Valid state scheme: hash and path. func ValidateStateScheme(stateScheme string) bool { @@ -335,7 +357,12 @@ 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. - stored := ReadStateScheme(disk) + var stored string + if disk.StateStore() != nil { + stored = ReadStateSchemeByStateDB(disk, disk.StateStore()) + } else { + stored = ReadStateScheme(disk) + } if provided == "" { if stored == "" { // use default scheme for empty database, flip it when diff --git a/core/rawdb/database.go b/core/rawdb/database.go index f27d96d13a..4c859d8618 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -41,7 +41,8 @@ type freezerdb struct { ancientRoot string ethdb.KeyValueStore ethdb.AncientStore - diffStore ethdb.KeyValueStore + diffStore ethdb.KeyValueStore + stateStore ethdb.Database } // AncientDatadir returns the path of root ancient directory. @@ -64,6 +65,11 @@ func (frdb *freezerdb) Close() error { errs = append(errs, err) } } + if frdb.stateStore != nil { + if err := frdb.stateStore.Close(); err != nil { + errs = append(errs, err) + } + } if len(errs) != 0 { return fmt.Errorf("%v", errs) } @@ -81,6 +87,17 @@ func (frdb *freezerdb) SetDiffStore(diff ethdb.KeyValueStore) { frdb.diffStore = diff } +func (frdb *freezerdb) StateStore() ethdb.Database { + return frdb.stateStore +} + +func (frdb *freezerdb) SetStateStore(state ethdb.Database) { + if frdb.stateStore != nil { + frdb.stateStore.Close() + } + frdb.stateStore = state +} + // Freeze is a helper method used for external testing to trigger and block until // a freeze cycle completes, without having to sleep for a minute to trigger the // automatic background run. @@ -104,7 +121,8 @@ func (frdb *freezerdb) Freeze(threshold uint64) error { // nofreezedb is a database wrapper that disables freezer data retrievals. type nofreezedb struct { ethdb.KeyValueStore - diffStore ethdb.KeyValueStore + diffStore ethdb.KeyValueStore + stateStore ethdb.Database } // HasAncient returns an error as we don't have a backing chain freezer. @@ -170,6 +188,14 @@ func (db *nofreezedb) SetDiffStore(diff ethdb.KeyValueStore) { db.diffStore = diff } +func (db *nofreezedb) StateStore() ethdb.Database { + return db.stateStore +} + +func (db *nofreezedb) SetStateStore(state ethdb.Database) { + db.stateStore = state +} + 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 509bdbc94e..8b81329f35 100644 --- a/core/rawdb/table.go +++ b/core/rawdb/table.go @@ -213,6 +213,14 @@ func (t *table) SetDiffStore(diff ethdb.KeyValueStore) { panic("not implement") } +func (t *table) StateStore() ethdb.Database { + return nil +} + +func (t *table) SetStateStore(state ethdb.Database) { + panic("not implement") +} + // 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/eth/backend.go b/eth/backend.go index 86ccf2475c..c7790b4a9f 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -21,7 +21,6 @@ import ( "errors" "fmt" "math/big" - "path/filepath" "runtime" "sync" @@ -70,7 +69,6 @@ import ( const ( ChainDBNamespace = "eth/db/chaindata/" - StateDBNamespace = "eth/db/statedata/" ) // Config contains the configuration options of the ETH protocol. @@ -139,23 +137,12 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { } // Assemble the Ethereum object - var chainDb ethdb.Database - var err error - if stack.Config().EnableSeparateTrie || stack.HasSeparateTrieDir() { - // It is the separated db which contain snapshot, meta and block data with no trie data storing in it. - // Allocate partial handles and cache to this separate database because it is not a complete database. - chainDb, err = stack.OpenAndMergeDatabase("chaindata", int(float64(config.DatabaseCache)*0.6), int(float64(config.DatabaseHandles)*0.6), - config.DatabaseFreezer, config.DatabaseDiff, ChainDBNamespace, false, config.PersistDiff, config.PruneAncientData) - if err != nil { - return nil, err - } - } else { - chainDb, err = stack.OpenAndMergeDatabase("chaindata", config.DatabaseCache, config.DatabaseHandles, - config.DatabaseFreezer, config.DatabaseDiff, ChainDBNamespace, false, config.PersistDiff, config.PruneAncientData) - if err != nil { - return nil, err - } + chainDb, err := stack.OpenAndMergeDatabase("chaindata", config.DatabaseCache, config.DatabaseHandles, + config.DatabaseFreezer, config.DatabaseDiff, ChainDBNamespace, false, config.PersistDiff, config.PruneAncientData) + if err != nil { + return nil, err } + config.StateScheme, err = rawdb.ParseStateScheme(config.StateScheme, chainDb) if err != nil { return nil, err @@ -293,25 +280,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { peers := newPeerSet() bcOps = append(bcOps, core.EnableBlockValidator(chainConfig, eth.engine, config.TriesVerifyMode, peers)) - // if the separated trie db has set, need to new blockchain with the separated trie database - if stack.Config().EnableSeparateTrie || stack.HasSeparateTrieDir() { - ancientDir := config.DatabaseFreezer - if ancientDir == "" { - ancientDir = "ancient" - } - // Allocate partial handles and cache to this separated database. - stateDirectory := filepath.Join(stack.ResolvePath("chaindata"), "state") - stateDBConfig := &core.StateDatabaseConfig{ - StateHandles: int(float64(config.DatabaseHandles) * 0.5), - StateCache: int(float64(config.DatabaseCache) * 0.5), - StateEngine: stack.Config().DBEngine, - StateDataDir: stateDirectory, - NameSpace: StateDBNamespace, - StateAncient: ancientDir, - } - cacheConfig.StateDiskDBConfig = stateDBConfig - } - eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, eth.shouldPreserve, &config.TransactionHistory, bcOps...) if err != nil { return nil, err diff --git a/ethdb/database.go b/ethdb/database.go index 5af19e3478..12404a521c 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -189,12 +189,18 @@ type DiffStore interface { SetDiffStore(diff KeyValueStore) } +type StateStore interface { + StateStore() Database + SetStateStore(state Database) +} + // Database contains all the methods required by the high level database to not // only access the key-value data store but also the chain freezer. type Database interface { Reader Writer DiffStore + StateStore Batcher Iteratee Stater diff --git a/ethdb/remotedb/remotedb.go b/ethdb/remotedb/remotedb.go index babb625d88..b4f84e28aa 100644 --- a/ethdb/remotedb/remotedb.go +++ b/ethdb/remotedb/remotedb.go @@ -94,6 +94,14 @@ func (db *Database) SetDiffStore(diff ethdb.KeyValueStore) { panic("not supported") } +func (db *Database) StateStore() ethdb.Database { + panic("not supported") +} + +func (db *Database) SetStateStore(state ethdb.Database) { + panic("not supported") +} + 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 9ee26d14dc..220822ac96 100644 --- a/node/node.go +++ b/node/node.go @@ -789,10 +789,30 @@ func (n *Node) OpenAndMergeDatabase(name string, cache, handles int, freezer, di if persistDiff { chainDataHandles = handles * chainDataHandlesPercentage / 100 } + var statediskdb ethdb.Database + var err error + // 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, int(float64(cache)*0.5), int(float64(chainDataHandles)*0.5), "", "eth/db/statedata/", readonly, false, false, pruneAncientData, true) + if err != nil { + return nil, err + } + + // Reduce the handles and cache to this separate database because it is not a complete database with no trie data storing in it. + cache = int(float64(cache) * 0.6) + chainDataHandles = int(float64(chainDataHandles) * 0.6) + } + chainDB, err := n.OpenDatabaseWithFreezer(name, cache, chainDataHandles, freezer, namespace, readonly, false, false, pruneAncientData, false) if err != nil { return nil, err } + + if statediskdb != nil { + chainDB.SetStateStore(statediskdb) + } + if persistDiff { diffStore, err := n.OpenDiffDatabase(name, handles-chainDataHandles, diff, namespace, readonly) if err != nil { @@ -825,7 +845,6 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient, } else { var dirName, ancientDirName string if isSeparateStateDB { - // set the directory name as state when opening a separate database, dirName = filepath.Join(n.ResolvePath(name), "state") ancientDirName = filepath.Join(dirName, "ancient") } else { diff --git a/trie/database.go b/trie/database.go index aaa20257a5..583d876c72 100644 --- a/trie/database.go +++ b/trie/database.go @@ -91,7 +91,16 @@ 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. - dbScheme := rawdb.ReadStateScheme(diskdb) + var dbScheme string + var statedb ethdb.Database + if diskdb.StateStore() != nil { + dbScheme = rawdb.ReadStateSchemeByStateDB(diskdb, diskdb.StateStore()) + statedb = diskdb.StateStore() + } else { + dbScheme = rawdb.ReadStateScheme(diskdb) + statedb = diskdb + } + if config == nil { if dbScheme == rawdb.PathScheme { config = &Config{ @@ -110,11 +119,11 @@ func NewDatabase(diskdb ethdb.Database, config *Config) *Database { } var preimages *preimageStore if config.Preimages { - preimages = newPreimageStore(diskdb) + preimages = newPreimageStore(statedb) } db := &Database{ config: config, - diskdb: diskdb, + diskdb: statedb, preimages: preimages, } /* @@ -123,25 +132,25 @@ func NewDatabase(diskdb ethdb.Database, config *Config) *Database { * 3. Last, use the default scheme, namely hash scheme */ if config.HashDB != nil { - if rawdb.ReadStateScheme(diskdb) == rawdb.PathScheme { + if rawdb.ReadStateScheme(statedb) == rawdb.PathScheme { log.Warn("incompatible state scheme", "old", rawdb.PathScheme, "new", rawdb.HashScheme) } - db.backend = hashdb.New(diskdb, config.HashDB, mptResolver{}) + db.backend = hashdb.New(statedb, config.HashDB, mptResolver{}) } else if config.PathDB != nil { - if rawdb.ReadStateScheme(diskdb) == rawdb.HashScheme { + if rawdb.ReadStateScheme(statedb) == rawdb.HashScheme { log.Warn("incompatible state scheme", "old", rawdb.HashScheme, "new", rawdb.PathScheme) } - db.backend = pathdb.New(diskdb, config.PathDB) + db.backend = pathdb.New(statedb, config.PathDB) } else if strings.Compare(dbScheme, rawdb.PathScheme) == 0 { if config.PathDB == nil { config.PathDB = pathdb.Defaults } - db.backend = pathdb.New(diskdb, config.PathDB) + db.backend = pathdb.New(statedb, config.PathDB) } else { if config.HashDB == nil { config.HashDB = hashdb.Defaults } - db.backend = hashdb.New(diskdb, config.HashDB, mptResolver{}) + db.backend = hashdb.New(statedb, config.HashDB, mptResolver{}) } return db } From 5d61f92d7fae61ff7b88999d3b4bf59f5485cc46 Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Tue, 20 Feb 2024 15:24:23 +0800 Subject: [PATCH 11/18] fix: fix state related commands --- cmd/geth/dbcmd.go | 103 +++++++++++++++++++---------------- cmd/geth/snapshot.go | 16 +++++- cmd/utils/flags.go | 9 ++- core/rawdb/accessors_trie.go | 2 +- core/rawdb/database.go | 8 +-- core/state/pruner/pruner.go | 41 ++++++++++---- node/node.go | 2 +- trie/database.go | 24 ++++---- 8 files changed, 122 insertions(+), 83 deletions(-) diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index 5a2721c973..e892bbd3df 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -381,11 +381,6 @@ func inspectTrie(ctx *cli.Context) error { db := utils.MakeChainDatabase(ctx, stack, true, false) defer db.Close() - var statediskdb ethdb.Database - if stack.HasSeparateTrieDir() { - statediskdb = utils.MakeStateDataBase(ctx, stack, true, false) - defer statediskdb.Close() - } var headerBlockHash common.Hash if ctx.NArg() >= 1 { if ctx.Args().Get(0) == "latest" { @@ -425,7 +420,12 @@ func inspectTrie(ctx *cli.Context) error { } fmt.Printf("ReadBlockHeader, root: %v, blocknum: %v\n", trieRootHash, blockNumber) - dbScheme := rawdb.ReadStateScheme(db) + var dbScheme string + if db.StateStore() != nil { + dbScheme = rawdb.ReadStateSchemeByStateDB(db, db.StateStore()) + } else { + dbScheme = rawdb.ReadStateScheme(db) + } var config *trie.Config if dbScheme == rawdb.PathScheme { config = &trie.Config{ @@ -435,12 +435,7 @@ func inspectTrie(ctx *cli.Context) error { config = trie.HashDefaults } - var triedb *trie.Database - if statediskdb != nil { - triedb = trie.NewDatabase(statediskdb, config) - } else { - triedb = trie.NewDatabase(db, config) - } + triedb := trie.NewDatabase(db, config) theTrie, err := trie.New(trie.TrieID(trieRootHash), triedb) if err != nil { fmt.Printf("fail to new trie tree, err: %v, rootHash: %v\n", err, trieRootHash.String()) @@ -484,12 +479,7 @@ func inspect(ctx *cli.Context) error { db := utils.MakeChainDatabase(ctx, stack, true, false) defer db.Close() - var statediskdb ethdb.Database - if stack.HasSeparateTrieDir() { - statediskdb = utils.MakeStateDataBase(ctx, stack, true, false) - defer statediskdb.Close() - } - return rawdb.InspectDatabase(db, statediskdb, prefix, start) + return rawdb.InspectDatabase(db, prefix, start) } func ancientInspect(ctx *cli.Context) error { @@ -521,6 +511,7 @@ func checkStateContent(ctx *cli.Context) error { db := utils.MakeChainDatabase(ctx, stack, true, false) defer db.Close() + var ( it = rawdb.NewKeyLengthIterator(db.NewIterator(prefix, start), 32) hasher = crypto.NewKeccakState() @@ -576,11 +567,9 @@ func dbStats(ctx *cli.Context) error { defer db.Close() showLeveldbStats(db) - if stack.HasSeparateTrieDir() { - statediskdb := utils.MakeStateDataBase(ctx, stack, true, false) - defer statediskdb.Close() - fmt.Println("show stats of separated db") - showLeveldbStats(statediskdb) + if db.StateStore() != nil { + fmt.Println("show stats of state store") + showLeveldbStats(db.StateStore()) } return nil @@ -596,10 +585,9 @@ func dbCompact(ctx *cli.Context) error { log.Info("Stats before compaction") showLeveldbStats(db) - var statediskdb ethdb.Database - if stack.HasSeparateTrieDir() { - statediskdb = utils.MakeStateDataBase(ctx, stack, false, false) - defer statediskdb.Close() + statediskdb := db.StateStore() + if statediskdb != nil { + fmt.Println("show stats of state store") showLeveldbStats(statediskdb) } @@ -619,6 +607,7 @@ func dbCompact(ctx *cli.Context) error { log.Info("Stats after compaction") showLeveldbStats(db) if statediskdb != nil { + fmt.Println("show stats of state store") showLeveldbStats(statediskdb) } return nil @@ -641,12 +630,11 @@ func dbGet(ctx *cli.Context) error { return err } + statediskdb := db.StateStore() data, err := db.Get(key) if err != nil { // if separate trie db exist, try to get it from separate db - if stack.HasSeparateTrieDir() { - statediskdb := utils.MakeStateDataBase(ctx, stack, true, false) - defer statediskdb.Close() + if statediskdb != nil { statedata, dberr := statediskdb.Get(key) if dberr == nil { fmt.Printf("key %#x: %#x\n", key, statedata) @@ -669,12 +657,13 @@ func dbTrieGet(ctx *cli.Context) error { defer stack.Close() var db ethdb.Database - if stack.HasSeparateTrieDir() { - db = utils.MakeStateDataBase(ctx, stack, true, false) + chaindb := utils.MakeChainDatabase(ctx, stack, true, false) + if chaindb.StateStore() != nil { + db = chaindb.StateStore() } else { - db = utils.MakeChainDatabase(ctx, stack, true, false) + db = chaindb } - defer db.Close() + defer chaindb.Close() scheme := ctx.String(utils.StateSchemeFlag.Name) if scheme == "" { @@ -740,12 +729,13 @@ func dbTrieDelete(ctx *cli.Context) error { defer stack.Close() var db ethdb.Database - if stack.HasSeparateTrieDir() { - db = utils.MakeStateDataBase(ctx, stack, true, false) + chaindb := utils.MakeChainDatabase(ctx, stack, true, false) + if chaindb.StateStore() != nil { + db = chaindb.StateStore() } else { - db = utils.MakeChainDatabase(ctx, stack, true, false) + db = chaindb } - defer db.Close() + defer chaindb.Close() scheme := ctx.String(utils.StateSchemeFlag.Name) if scheme == "" { @@ -866,12 +856,7 @@ func dbDumpTrie(ctx *cli.Context) error { stack, _ := makeConfigNode(ctx) defer stack.Close() - var db ethdb.Database - if stack.HasSeparateTrieDir() { - db = utils.MakeStateDataBase(ctx, stack, true, false) - } else { - db = utils.MakeChainDatabase(ctx, stack, true, false) - } + db := utils.MakeChainDatabase(ctx, stack, true, false) defer db.Close() triedb := utils.MakeTrieDatabase(ctx, db, false, true, false) @@ -1140,10 +1125,16 @@ func hbss2pbss(ctx *cli.Context) error { db := utils.MakeChainDatabase(ctx, stack, false, false) db.Sync() + statediskdb := db.StateStore() defer db.Close() // convert hbss trie node to pbss trie node - lastStateID := rawdb.ReadPersistentStateID(db) + var lastStateID uint64 + if statediskdb != nil { + lastStateID = rawdb.ReadPersistentStateID(statediskdb) + } else { + lastStateID = rawdb.ReadPersistentStateID(db) + } if lastStateID == 0 || force { config := trie.HashDefaults triedb := trie.NewDatabase(db, config) @@ -1195,18 +1186,34 @@ func hbss2pbss(ctx *cli.Context) error { } // repair state ancient offset - lastStateID = rawdb.ReadPersistentStateID(db) + if statediskdb != nil { + lastStateID = rawdb.ReadPersistentStateID(statediskdb) + } else { + lastStateID = rawdb.ReadPersistentStateID(db) + } + if lastStateID == 0 { log.Error("Convert hbss to pbss trie node error. The last state id is still 0") } - ancient := stack.ResolveAncient("chaindata", ctx.String(utils.AncientFlag.Name)) + + var ancient string + if db.StateStore() != nil { + dirName := filepath.Join(stack.ResolvePath("chaindata"), "state") + ancient = filepath.Join(dirName, "ancient") + } else { + ancient = stack.ResolveAncient("chaindata", ctx.String(utils.AncientFlag.Name)) + } err = rawdb.ResetStateFreezerTableOffset(ancient, lastStateID) if err != nil { log.Error("Reset state freezer table offset failed", "error", err) return err } // prune hbss trie node - err = rawdb.PruneHashTrieNodeInDataBase(db) + if statediskdb != nil { + err = rawdb.PruneHashTrieNodeInDataBase(statediskdb) + } else { + err = rawdb.PruneHashTrieNodeInDataBase(db) + } if err != nil { log.Error("Prune Hash trie node in database failed", "error", err) return err diff --git a/cmd/geth/snapshot.go b/cmd/geth/snapshot.go index 73453c0f91..f26e67dc78 100644 --- a/cmd/geth/snapshot.go +++ b/cmd/geth/snapshot.go @@ -244,6 +244,7 @@ func accessDb(ctx *cli.Context, stack *node.Node) (ethdb.Database, error) { NoBuild: true, AsyncBuild: false, } + snaptree, err := snapshot.New(snapconfig, chaindb, trie.NewDatabase(chaindb, nil), headBlock.Root(), TriesInMemory, false) if err != nil { log.Error("snaptree error", "err", err) @@ -436,13 +437,21 @@ func pruneState(ctx *cli.Context) error { chaindb := utils.MakeChainDatabase(ctx, stack, false, false) defer chaindb.Close() - if rawdb.ReadStateScheme(chaindb) != rawdb.HashScheme { - log.Crit("Offline pruning is not required for path scheme") - } prunerconfig := pruner.Config{ Datadir: stack.ResolvePath(""), 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") + } + } + pruner, err := pruner.NewPruner(chaindb, prunerconfig, ctx.Uint64(utils.TriesInMemoryFlag.Name)) if err != nil { log.Error("Failed to open snapshot tree", "err", err) @@ -498,6 +507,7 @@ func pruneAllState(ctx *cli.Context) error { chaindb := utils.MakeChainDatabase(ctx, stack, false, false) defer chaindb.Close() + pruner, err := pruner.NewAllPruner(chaindb) if err != nil { log.Error("Failed to open snapshot tree", "err", err) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index f8bb9810fc..8b3066d291 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -2324,6 +2324,11 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFree chainDb, err = stack.OpenDatabase("lightchaindata", cache, handles, "", readonly) default: chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly, disableFreeze, false, false, false) + // set the separate state database + if stack.HasSeparateTrieDir() && err == nil { + statediskdb := MakeStateDataBase(ctx, stack, readonly, false) + chainDb.SetStateStore(statediskdb) + } } if err != nil { Fatalf("Could not open database: %v", err) @@ -2334,7 +2339,7 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFree // MakeStateDataBase open a separate state database using the flags passed to the client and will hard crash if it fails. func MakeStateDataBase(ctx *cli.Context, stack *node.Node, readonly, disableFreeze bool) ethdb.Database { cache := ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100 - handles := MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name)) + handles := MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name)) / 2 statediskdb, err := stack.OpenDatabaseWithFreezer("chaindata", cache, handles, "", "", readonly, disableFreeze, false, false, true) if err != nil { Fatalf("Failed to open separate trie database: %v", err) @@ -2424,7 +2429,6 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh if err != nil { Fatalf("%v", err) } - cache := &core.CacheConfig{ TrieCleanLimit: ethconfig.Defaults.TrieCleanCache, TrieCleanNoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name), @@ -2437,7 +2441,6 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh StateScheme: scheme, StateHistory: ctx.Uint64(StateHistoryFlag.Name), } - if cache.TrieDirtyDisabled && !cache.Preimages { cache.Preimages = true log.Info("Enabling recording of key preimages since archive mode is used") diff --git a/core/rawdb/accessors_trie.go b/core/rawdb/accessors_trie.go index f4a0adc16b..bb62ac0aef 100644 --- a/core/rawdb/accessors_trie.go +++ b/core/rawdb/accessors_trie.go @@ -358,7 +358,7 @@ func ParseStateScheme(provided string, disk ethdb.Database) (string, error) { // with persistent state, or fallback to hash mode if database // is empty. var stored string - if disk.StateStore() != nil { + if disk != nil && disk.StateStore() != nil { stored = ReadStateSchemeByStateDB(disk, disk.StateStore()) } else { stored = ReadStateScheme(disk) diff --git a/core/rawdb/database.go b/core/rawdb/database.go index 4c859d8618..ace6d82216 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -645,13 +645,13 @@ func inspectTrieData(key, value []byte, legacyTries, accountTries, storageTries, // InspectDatabase traverses the entire database and checks the size // of all different categories of data. -func InspectDatabase(db ethdb.Database, separateDB ethdb.Database, keyPrefix, keyStart []byte) error { +func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { it := db.NewIterator(keyPrefix, keyStart) defer it.Release() var trieIter ethdb.Iterator - if separateDB != nil { - trieIter = separateDB.NewIterator(keyPrefix, nil) + if db.StateStore() != nil { + trieIter = db.StateStore().NewIterator(keyPrefix, nil) defer trieIter.Release() } var ( @@ -841,7 +841,7 @@ func InspectDatabase(db ethdb.Database, separateDB ethdb.Database, keyPrefix, ke // inspect ancient state in separate trie db if exist if trieIter != nil { - stateAncients, err := inspectFreezers(separateDB) + stateAncients, err := inspectFreezers(db.StateStore()) if err != nil { return err } diff --git a/core/state/pruner/pruner.go b/core/state/pruner/pruner.go index 396c51dff1..57633742fc 100644 --- a/core/state/pruner/pruner.go +++ b/core/state/pruner/pruner.go @@ -158,13 +158,19 @@ func (p *Pruner) PruneAll(genesis *core.Genesis) error { } func pruneAll(maindb ethdb.Database, g *core.Genesis) error { + var pruneDB ethdb.Database + if maindb != nil && maindb.StateStore() != nil { + pruneDB = maindb.StateStore() + } else { + pruneDB = maindb + } var ( count int size common.StorageSize pstart = time.Now() logged = time.Now() - batch = maindb.NewBatch() - iter = maindb.NewIterator(nil, nil) + batch = pruneDB.NewBatch() + iter = pruneDB.NewIterator(nil, nil) ) start := time.Now() for iter.Next() { @@ -194,7 +200,7 @@ func pruneAll(maindb ethdb.Database, g *core.Genesis) error { batch.Reset() iter.Release() - iter = maindb.NewIterator(nil, key) + iter = pruneDB.NewIterator(nil, key) } } } @@ -218,7 +224,7 @@ func pruneAll(maindb ethdb.Database, g *core.Genesis) error { end = nil } log.Info("Compacting database", "range", fmt.Sprintf("%#x-%#x", start, end), "elapsed", common.PrettyDuration(time.Since(cstart))) - if err := maindb.Compact(start, end); err != nil { + if err := pruneDB.Compact(start, end); err != nil { log.Error("Database compaction failed", "error", err) return err } @@ -249,13 +255,19 @@ func prune(snaptree *snapshot.Tree, root common.Hash, maindb ethdb.Database, sta // that the false-positive is low enough(~0.05%). The probablity of the // dangling node is the state root is super low. So the dangling nodes in // theory will never ever be visited again. + var pruneDB ethdb.Database + if maindb != nil && maindb.StateStore() != nil { + pruneDB = maindb.StateStore() + } else { + pruneDB = maindb + } var ( skipped, count int size common.StorageSize pstart = time.Now() logged = time.Now() - batch = maindb.NewBatch() - iter = maindb.NewIterator(nil, nil) + batch = pruneDB.NewBatch() + iter = pruneDB.NewIterator(nil, nil) ) for iter.Next() { key := iter.Key() @@ -302,7 +314,7 @@ func prune(snaptree *snapshot.Tree, root common.Hash, maindb ethdb.Database, sta batch.Reset() iter.Release() - iter = maindb.NewIterator(nil, key) + iter = pruneDB.NewIterator(nil, key) } } } @@ -347,7 +359,7 @@ func prune(snaptree *snapshot.Tree, root common.Hash, maindb ethdb.Database, sta end = nil } log.Info("Compacting database", "range", fmt.Sprintf("%#x-%#x", start, end), "elapsed", common.PrettyDuration(time.Since(cstart))) - if err := maindb.Compact(start, end); err != nil { + if err := pruneDB.Compact(start, end); err != nil { log.Error("Database compaction failed", "error", err) return err } @@ -585,10 +597,17 @@ func (p *Pruner) Prune(root common.Hash) error { // Use the bottom-most diff layer as the target root = layers[len(layers)-1].Root() } + // if the separated state db has been set, use this db to prune data + var trienodedb ethdb.Database + if p.db != nil && p.db.StateStore() != nil { + trienodedb = p.db.StateStore() + } else { + trienodedb = p.db + } // Ensure the root is really present. The weak assumption // is the presence of root can indicate the presence of the // entire trie. - if !rawdb.HasLegacyTrieNode(p.db, root) { + if !rawdb.HasLegacyTrieNode(trienodedb, root) { // The special case is for clique based networks(goerli // and some other private networks), it's possible that two // consecutive blocks will have same root. In this case snapshot @@ -602,7 +621,7 @@ func (p *Pruner) Prune(root common.Hash) error { // as the pruning target. var found bool for i := len(layers) - 2; i >= 2; i-- { - if rawdb.HasLegacyTrieNode(p.db, layers[i].Root()) { + if rawdb.HasLegacyTrieNode(trienodedb, layers[i].Root()) { root = layers[i].Root() found = true log.Info("Selecting middle-layer as the pruning target", "root", root, "depth", i) @@ -610,7 +629,7 @@ func (p *Pruner) Prune(root common.Hash) error { } } if !found { - if blob := rawdb.ReadLegacyTrieNode(p.db, p.snaptree.DiskRoot()); len(blob) != 0 { + if blob := rawdb.ReadLegacyTrieNode(trienodedb, p.snaptree.DiskRoot()); len(blob) != 0 { root = p.snaptree.DiskRoot() found = true log.Info("Selecting disk-layer as the pruning target", "root", root) diff --git a/node/node.go b/node/node.go index 220822ac96..395219d1b5 100644 --- a/node/node.go +++ b/node/node.go @@ -794,7 +794,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, int(float64(cache)*0.5), int(float64(chainDataHandles)*0.5), "", "eth/db/statedata/", readonly, false, false, pruneAncientData, true) + statediskdb, err = n.OpenDatabaseWithFreezer(name, cache/2, chainDataHandles/2, "", "eth/db/statedata/", readonly, false, false, pruneAncientData, true) if err != nil { return nil, err } diff --git a/trie/database.go b/trie/database.go index 583d876c72..5087e2eac8 100644 --- a/trie/database.go +++ b/trie/database.go @@ -92,13 +92,13 @@ type Database struct { 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 statedb ethdb.Database - if diskdb.StateStore() != nil { + var statediskdb ethdb.Database + if diskdb != nil && diskdb.StateStore() != nil { dbScheme = rawdb.ReadStateSchemeByStateDB(diskdb, diskdb.StateStore()) - statedb = diskdb.StateStore() + statediskdb = diskdb.StateStore() } else { dbScheme = rawdb.ReadStateScheme(diskdb) - statedb = diskdb + statediskdb = diskdb } if config == nil { @@ -119,11 +119,11 @@ func NewDatabase(diskdb ethdb.Database, config *Config) *Database { } var preimages *preimageStore if config.Preimages { - preimages = newPreimageStore(statedb) + preimages = newPreimageStore(statediskdb) } db := &Database{ config: config, - diskdb: statedb, + diskdb: statediskdb, preimages: preimages, } /* @@ -132,25 +132,25 @@ func NewDatabase(diskdb ethdb.Database, config *Config) *Database { * 3. Last, use the default scheme, namely hash scheme */ if config.HashDB != nil { - if rawdb.ReadStateScheme(statedb) == rawdb.PathScheme { + if rawdb.ReadStateScheme(statediskdb) == rawdb.PathScheme { log.Warn("incompatible state scheme", "old", rawdb.PathScheme, "new", rawdb.HashScheme) } - db.backend = hashdb.New(statedb, config.HashDB, mptResolver{}) + db.backend = hashdb.New(statediskdb, config.HashDB, mptResolver{}) } else if config.PathDB != nil { - if rawdb.ReadStateScheme(statedb) == rawdb.HashScheme { + if rawdb.ReadStateScheme(statediskdb) == rawdb.HashScheme { log.Warn("incompatible state scheme", "old", rawdb.HashScheme, "new", rawdb.PathScheme) } - db.backend = pathdb.New(statedb, config.PathDB) + db.backend = pathdb.New(statediskdb, config.PathDB) } else if strings.Compare(dbScheme, rawdb.PathScheme) == 0 { if config.PathDB == nil { config.PathDB = pathdb.Defaults } - db.backend = pathdb.New(statedb, config.PathDB) + db.backend = pathdb.New(statediskdb, config.PathDB) } else { if config.HashDB == nil { config.HashDB = hashdb.Defaults } - db.backend = hashdb.New(statedb, config.HashDB, mptResolver{}) + db.backend = hashdb.New(statediskdb, config.HashDB, mptResolver{}) } return db } From aaa19172d224858a68195dd06832aa64410138b0 Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Fri, 23 Feb 2024 14:35:28 +0800 Subject: [PATCH 12/18] fix: remove unuse code --- cmd/geth/dbcmd.go | 1 - cmd/geth/snapshot.go | 2 -- cmd/utils/flags.go | 3 --- core/blockchain.go | 46 +++++++++++++++----------------------------- node/config.go | 7 ------- node/node.go | 5 ----- 6 files changed, 16 insertions(+), 48 deletions(-) diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index e892bbd3df..94f3883367 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -511,7 +511,6 @@ func checkStateContent(ctx *cli.Context) error { db := utils.MakeChainDatabase(ctx, stack, true, false) defer db.Close() - var ( it = rawdb.NewKeyLengthIterator(db.NewIterator(prefix, start), 32) hasher = crypto.NewKeccakState() diff --git a/cmd/geth/snapshot.go b/cmd/geth/snapshot.go index f26e67dc78..781c78ed1c 100644 --- a/cmd/geth/snapshot.go +++ b/cmd/geth/snapshot.go @@ -244,7 +244,6 @@ func accessDb(ctx *cli.Context, stack *node.Node) (ethdb.Database, error) { NoBuild: true, AsyncBuild: false, } - snaptree, err := snapshot.New(snapconfig, chaindb, trie.NewDatabase(chaindb, nil), headBlock.Root(), TriesInMemory, false) if err != nil { log.Error("snaptree error", "err", err) @@ -507,7 +506,6 @@ func pruneAllState(ctx *cli.Context) error { chaindb := utils.MakeChainDatabase(ctx, stack, false, false) defer chaindb.Close() - pruner, err := pruner.NewAllPruner(chaindb) if err != nil { log.Error("Failed to open snapshot tree", "err", err) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 8b3066d291..78df59aa17 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1640,9 +1640,6 @@ func SetDataDir(ctx *cli.Context, cfg *node.Config) { case ctx.Bool(DeveloperFlag.Name): cfg.DataDir = "" // unless explicitly requested, use memory databases } - if ctx.IsSet(SeparateTrieFlag.Name) { - cfg.EnableSeparateTrie = true - } } func setVoteJournalDir(ctx *cli.Context, cfg *node.Config) { diff --git a/core/blockchain.go b/core/blockchain.go index dcc8ec65fa..5141169986 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -165,20 +165,8 @@ type CacheConfig struct { StateScheme string // Scheme used to store ethereum states and merkle tree nodes on top PathSyncFlush bool // Whether sync flush the trienodebuffer of pathdb to disk. - SnapshotNoBuild bool // Whether the background generation is allowed - SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it - StateDiskDBConfig *StateDatabaseConfig // The configuration of the separated single trie database -} - -// StateDatabaseConfig contains the configuration values of the separated single state database -type StateDatabaseConfig struct { - StateHandles int // The handler num used by the separated state db - StateCache int // The cache size used by the separated state db - StateEngine string // The db engine (pebble or leveldb) used by the separated state db - StateDataDir string // The directory of the separated state db - NameSpace string // The namespace of the separated state db - StateAncient string // The ancient directory of the separated state db - PruneAncientData bool + SnapshotNoBuild bool // Whether the background generation is allowed + SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it } // triedbConfig derives the configures for trie database. @@ -336,6 +324,17 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis diffLayerCache, _ := exlru.New(diffLayerCacheLimit) diffLayerChanCache, _ := exlru.New(diffLayerCacheLimit) + // Open trie database with provided config + triedb := trie.NewDatabase(db, cacheConfig.triedbConfig()) + // Setup the genesis block, commit the provided genesis specification + // to database if the genesis block is not present yet, or load the + // stored one from database. + chainConfig, genesisHash, genesisErr := SetupGenesisBlockWithOverride(db, triedb, genesis, overrides) + if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { + return nil, genesisErr + } + systemcontracts.GenesisHash = genesisHash + log.Info("Initialised chain configuration", "config", chainConfig) // Description of chainConfig is empty now /* log.Info("") @@ -348,8 +347,10 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis */ bc := &BlockChain{ + chainConfig: chainConfig, cacheConfig: cacheConfig, db: db, + triedb: triedb, triegc: prque.New[int64, common.Hash](nil), quit: make(chan struct{}), triesInMemory: cacheConfig.TriesInMemory, @@ -368,22 +369,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis diffQueue: prque.New[int64, *types.DiffLayer](nil), diffQueueBuffer: make(chan *types.DiffLayer), } - var err error - - // Open trie database with provided config - triedb := trie.NewDatabase(db, cacheConfig.triedbConfig()) - bc.triedb = triedb - // Setup the genesis block, commit the provided genesis specification - // to database if the genesis block is not present yet, or load the - // stored one from database. - chainConfig, genesisHash, genesisErr := SetupGenesisBlockWithOverride(db, triedb, genesis, overrides) - if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { - return nil, genesisErr - } - bc.chainConfig = chainConfig - systemcontracts.GenesisHash = genesisHash - log.Info("Initialised chain configuration", "config", chainConfig) - bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit)) bc.forker = NewForkChoice(bc, shouldPreserve) bc.stateCache = state.NewDatabaseWithNodeDB(bc.db, bc.triedb) @@ -391,6 +376,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis bc.prefetcher = NewStatePrefetcher(chainConfig, bc, engine) bc.processor = NewStateProcessor(chainConfig, bc, engine) + var err error bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.insertStopped) if err != nil { return nil, err diff --git a/node/config.go b/node/config.go index be75dd50da..bc30a0ab0a 100644 --- a/node/config.go +++ b/node/config.go @@ -64,9 +64,6 @@ type Config struct { // in memory. DataDir string - // EnableSeparateTrie is a flag that whether to enable the separated single trie database - EnableSeparateTrie bool `toml:",omitempty"` - // Configuration of peer-to-peer networking. P2P p2p.Config @@ -441,10 +438,6 @@ func (c *Config) checkLegacyFiles() { c.checkLegacyFile(c.ResolvePath(datadirTrustedNodes)) } -func (c *Config) enableSeparateTrie() { - c.EnableSeparateTrie = true -} - // checkLegacyFile will only raise an error if a file at the given path exists. func (c *Config) checkLegacyFile(path string) { // Short circuit if no node config is present diff --git a/node/node.go b/node/node.go index 395219d1b5..6bd59a6d99 100644 --- a/node/node.go +++ b/node/node.go @@ -90,7 +90,6 @@ func New(conf *Config) (*Node, error) { } conf.DataDir = absdatadir } - if conf.LogConfig != nil { if conf.LogConfig.TermTimeFormat != nil && *conf.LogConfig.TermTimeFormat != "" { log.SetTermTimeFormat(*conf.LogConfig.TermTimeFormat) @@ -180,10 +179,6 @@ func New(conf *Config) (*Node, error) { node.server.Config.NodeDatabase = node.config.NodeDB() } - if conf.EnableSeparateTrie { - node.config.enableSeparateTrie() - } - // Check HTTP/WS prefixes are valid. if err := validatePrefix("HTTP", conf.HTTPPathPrefix); err != nil { return nil, err From fc95001def5d5b489df768a123aaddbd2e2085cd Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Mon, 26 Feb 2024 18:05:43 +0800 Subject: [PATCH 13/18] fix: fix inspect db --- core/rawdb/database.go | 43 +++++++++++++++++++++--------------------- trie/database.go | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/core/rawdb/database.go b/core/rawdb/database.go index ace6d82216..0811f170d4 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -629,20 +629,6 @@ func PruneHashTrieNodeInDataBase(db ethdb.Database) error { return nil } -func inspectTrieData(key, value []byte, legacyTries, accountTries, storageTries, stateLookups *stat) { - size := common.StorageSize(len(key) + len(value)) - switch { - case IsLegacyTrieNode(key, value): - legacyTries.Add(size) - case bytes.HasPrefix(key, stateIDPrefix) && len(key) == len(stateIDPrefix)+common.HashLength: - stateLookups.Add(size) - case IsAccountTrieNode(key): - accountTries.Add(size) - case IsStorageTrieNode(key): - storageTries.Add(size) - } -} - // InspectDatabase traverses the entire database and checks the size // of all different categories of data. func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { @@ -783,17 +769,32 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { value = trieIter.Value() size = common.StorageSize(len(key) + len(value)) ) - inspectTrieData(key, value, &legacyTries, &accountTries, &storageTries, &stateLookups) - for _, meta := range [][]byte{ - fastTrieProgressKey, persistentStateIDKey, trieJournalKey} { - if bytes.Equal(key, meta) { - metadata.Add(size) - break + + switch { + case IsLegacyTrieNode(key, value): + legacyTries.Add(size) + case bytes.HasPrefix(key, stateIDPrefix) && len(key) == len(stateIDPrefix)+common.HashLength: + stateLookups.Add(size) + case IsAccountTrieNode(key): + accountTries.Add(size) + case IsStorageTrieNode(key): + storageTries.Add(size) + default: + var accounted bool + for _, meta := range [][]byte{ + fastTrieProgressKey, persistentStateIDKey, trieJournalKey} { + if bytes.Equal(key, meta) { + metadata.Add(size) + break + } + } + if !accounted { + unaccounted.Add(size) } } count++ if count%1000 == 0 && time.Since(logged) > 8*time.Second { - log.Info("Inspecting separate database", "count", count, "elapsed", common.PrettyDuration(time.Since(start))) + log.Info("Inspecting separate state database", "count", count, "elapsed", common.PrettyDuration(time.Since(start))) logged = time.Now() } } diff --git a/trie/database.go b/trie/database.go index 5087e2eac8..bd35d19351 100644 --- a/trie/database.go +++ b/trie/database.go @@ -92,13 +92,13 @@ type Database struct { 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 statediskdb ethdb.Database + var triediskdb ethdb.Database if diskdb != nil && diskdb.StateStore() != nil { dbScheme = rawdb.ReadStateSchemeByStateDB(diskdb, diskdb.StateStore()) - statediskdb = diskdb.StateStore() + triediskdb = diskdb.StateStore() } else { dbScheme = rawdb.ReadStateScheme(diskdb) - statediskdb = diskdb + triediskdb = diskdb } if config == nil { @@ -119,11 +119,11 @@ func NewDatabase(diskdb ethdb.Database, config *Config) *Database { } var preimages *preimageStore if config.Preimages { - preimages = newPreimageStore(statediskdb) + preimages = newPreimageStore(triediskdb) } db := &Database{ config: config, - diskdb: statediskdb, + diskdb: triediskdb, preimages: preimages, } /* @@ -132,25 +132,25 @@ func NewDatabase(diskdb ethdb.Database, config *Config) *Database { * 3. Last, use the default scheme, namely hash scheme */ if config.HashDB != nil { - if rawdb.ReadStateScheme(statediskdb) == rawdb.PathScheme { + if rawdb.ReadStateScheme(triediskdb) == rawdb.PathScheme { log.Warn("incompatible state scheme", "old", rawdb.PathScheme, "new", rawdb.HashScheme) } - db.backend = hashdb.New(statediskdb, config.HashDB, mptResolver{}) + db.backend = hashdb.New(triediskdb, config.HashDB, mptResolver{}) } else if config.PathDB != nil { - if rawdb.ReadStateScheme(statediskdb) == rawdb.HashScheme { + if rawdb.ReadStateScheme(triediskdb) == rawdb.HashScheme { log.Warn("incompatible state scheme", "old", rawdb.HashScheme, "new", rawdb.PathScheme) } - db.backend = pathdb.New(statediskdb, config.PathDB) + db.backend = pathdb.New(triediskdb, config.PathDB) } else if strings.Compare(dbScheme, rawdb.PathScheme) == 0 { if config.PathDB == nil { config.PathDB = pathdb.Defaults } - db.backend = pathdb.New(statediskdb, config.PathDB) + db.backend = pathdb.New(triediskdb, config.PathDB) } else { if config.HashDB == nil { config.HashDB = hashdb.Defaults } - db.backend = hashdb.New(statediskdb, config.HashDB, mptResolver{}) + db.backend = hashdb.New(triediskdb, config.HashDB, mptResolver{}) } return db } From 3e9870051a0cf2c355235b3caef0709d699c079b Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Tue, 5 Mar 2024 16:48:04 +0800 Subject: [PATCH 14/18] fix: add parameter judgement for separate db --- cmd/geth/chaincmd.go | 2 +- cmd/geth/config.go | 3 +++ cmd/utils/flags.go | 6 +++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 5361bc7087..1a59f999b7 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -238,7 +238,7 @@ func initGenesis(ctx *cli.Context) error { defer chaindb.Close() // if the trie data dir has been set, new trie db with a new state database - if ctx.IsSet(utils.SeparateTrieFlag.Name) { + if ctx.IsSet(utils.SeparateDBFlag.Name) { statediskdb, dbErr := stack.OpenDatabaseWithFreezer(name, 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/config.go b/cmd/geth/config.go index 94c2317e95..8f8f2b5f2d 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -203,6 +203,9 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { v := ctx.Uint64(utils.OverrideFeynman.Name) cfg.Eth.OverrideFeynman = &v } + if ctx.IsSet(utils.SeparateDBFlag.Name) && !stack.HasSeparateTrieDir() { + utils.Fatalf("Failed to locate separate database subdirectory when separatedb parameter has been set") + } backend, eth := utils.RegisterEthService(stack, &cfg.Eth) // Create gauge with geth system and build information diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 78df59aa17..48419ae5c3 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -93,8 +93,8 @@ var ( Value: flags.DirectoryString(node.DefaultDataDir()), Category: flags.EthCategory, } - SeparateTrieFlag = &cli.BoolFlag{ - Name: "separatetrie", + SeparateDBFlag = &cli.BoolFlag{ + Name: "separatedb", Usage: "Enable a separated trie database, it will be created within a subdirectory called state, " + "Users can copy this state directory to another directory or disk, and then create a symbolic link to the state directory under the chaindata", Category: flags.EthCategory, @@ -1118,7 +1118,7 @@ var ( DBEngineFlag, StateSchemeFlag, HttpHeaderFlag, - SeparateTrieFlag, + SeparateDBFlag, } ) From 58645bdc04fd44cc51846f57d15f499113df365d Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Wed, 6 Mar 2024 12:06:00 +0800 Subject: [PATCH 15/18] 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{ From c806e15021e0c965c6e536ec4d323c73500f7128 Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Wed, 6 Mar 2024 18:13:01 +0800 Subject: [PATCH 16/18] fix: fix comments --- cmd/geth/chaincmd.go | 4 ++-- cmd/geth/config.go | 2 +- cmd/geth/dbcmd.go | 14 +++++++------- cmd/utils/flags.go | 10 +++++----- core/state/pruner/pruner.go | 2 +- node/errors.go | 9 ++++----- node/node.go | 15 ++++++--------- 7 files changed, 26 insertions(+), 30 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 2ce1200e74..459a68bfc2 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -231,7 +231,7 @@ func initGenesis(ctx *cli.Context) error { overrides.OverrideVerkle = &v } for _, name := range []string{"chaindata", "lightchaindata"} { - chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.String(utils.AncientFlag.Name), "", false, false, false, false, false) + chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.String(utils.AncientFlag.Name), "", false, false, false, false) if err != nil { utils.Fatalf("Failed to open database: %v", err) } @@ -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+"/state", 0, 0, "", "", false, false, false, false, true) + statediskdb, dbErr := stack.OpenDatabaseWithFreezer(name+"/state", 0, 0, "", "", false, false, false, false) if dbErr != nil { utils.Fatalf("Failed to open separate trie database: %v", dbErr) } diff --git a/cmd/geth/config.go b/cmd/geth/config.go index 8f8f2b5f2d..6f7250aee1 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -203,7 +203,7 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { v := ctx.Uint64(utils.OverrideFeynman.Name) cfg.Eth.OverrideFeynman = &v } - if ctx.IsSet(utils.SeparateDBFlag.Name) && !stack.HasSeparateTrieDir() { + if ctx.IsSet(utils.SeparateDBFlag.Name) && !stack.IsSeparatedDB() { utils.Fatalf("Failed to locate separate database subdirectory when separatedb parameter has been set") } backend, eth := utils.RegisterEthService(stack, &cfg.Eth) diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index 17841cfdda..f552b1d660 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -1119,13 +1119,13 @@ func hbss2pbss(ctx *cli.Context) error { db := utils.MakeChainDatabase(ctx, stack, false, false) db.Sync() - statediskdb := db.StateStore() + stateDiskDb := db.StateStore() defer db.Close() // convert hbss trie node to pbss trie node var lastStateID uint64 - if statediskdb != nil { - lastStateID = rawdb.ReadPersistentStateID(statediskdb) + if stateDiskDb != nil { + lastStateID = rawdb.ReadPersistentStateID(stateDiskDb) } else { lastStateID = rawdb.ReadPersistentStateID(db) } @@ -1180,8 +1180,8 @@ func hbss2pbss(ctx *cli.Context) error { } // repair state ancient offset - if statediskdb != nil { - lastStateID = rawdb.ReadPersistentStateID(statediskdb) + if stateDiskDb != nil { + lastStateID = rawdb.ReadPersistentStateID(stateDiskDb) } else { lastStateID = rawdb.ReadPersistentStateID(db) } @@ -1203,8 +1203,8 @@ func hbss2pbss(ctx *cli.Context) error { return err } // prune hbss trie node - if statediskdb != nil { - err = rawdb.PruneHashTrieNodeInDataBase(statediskdb) + if stateDiskDb != nil { + err = rawdb.PruneHashTrieNodeInDataBase(stateDiskDb) } else { err = rawdb.PruneHashTrieNodeInDataBase(db) } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 48419ae5c3..0730aef76c 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -2320,11 +2320,11 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFree case ctx.String(SyncModeFlag.Name) == "light": chainDb, err = stack.OpenDatabase("lightchaindata", cache, handles, "", readonly) default: - chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly, disableFreeze, false, false, false) + chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly, disableFreeze, false, false) // set the separate state database - if stack.HasSeparateTrieDir() && err == nil { - statediskdb := MakeStateDataBase(ctx, stack, readonly, false) - chainDb.SetStateStore(statediskdb) + if stack.IsSeparatedDB() && err == nil { + stateDiskDb := MakeStateDataBase(ctx, stack, readonly, false) + chainDb.SetStateStore(stateDiskDb) } } if err != nil { @@ -2337,7 +2337,7 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFree func MakeStateDataBase(ctx *cli.Context, stack *node.Node, readonly, disableFreeze bool) ethdb.Database { cache := ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100 handles := MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name)) / 2 - statediskdb, err := stack.OpenDatabaseWithFreezer("chaindata", cache, handles, "", "", readonly, disableFreeze, false, false, true) + statediskdb, err := stack.OpenDatabaseWithFreezer("chaindata/state", cache, handles, "", "", readonly, disableFreeze, false, false) if err != nil { Fatalf("Failed to open separate trie database: %v", err) } diff --git a/core/state/pruner/pruner.go b/core/state/pruner/pruner.go index 57633742fc..7aa7b3af40 100644 --- a/core/state/pruner/pruner.go +++ b/core/state/pruner/pruner.go @@ -372,7 +372,7 @@ func prune(snaptree *snapshot.Tree, root common.Hash, maindb ethdb.Database, sta func (p *BlockPruner) backUpOldDb(name string, cache, handles int, namespace string, readonly, interrupt bool) error { // Open old db wrapper. - chainDb, err := p.node.OpenDatabaseWithFreezer(name, cache, handles, p.oldAncientPath, namespace, readonly, true, interrupt, false, false) + chainDb, err := p.node.OpenDatabaseWithFreezer(name, cache, handles, p.oldAncientPath, namespace, readonly, true, interrupt, false) if err != nil { log.Error("Failed to open ancient database", "err=", err) return err diff --git a/node/errors.go b/node/errors.go index e7f60ce9bc..67547bf691 100644 --- a/node/errors.go +++ b/node/errors.go @@ -24,11 +24,10 @@ import ( ) var ( - ErrDatadirUsed = errors.New("datadir already used by another process") - ErrNodeStopped = errors.New("node not started") - ErrNodeRunning = errors.New("node already running") - ErrServiceUnknown = errors.New("unknown service") - ErrSeprateDBDatadir = errors.New("datadir is not configured when using separate trie") + ErrDatadirUsed = errors.New("datadir already used by another process") + ErrNodeStopped = errors.New("node not started") + ErrNodeRunning = errors.New("node already running") + ErrServiceUnknown = errors.New("unknown service") datadirInUseErrnos = map[uint]bool{11: true, 32: true, 35: true} ) diff --git a/node/node.go b/node/node.go index dbd4f7a889..5d37334512 100644 --- a/node/node.go +++ b/node/node.go @@ -787,9 +787,9 @@ func (n *Node) OpenAndMergeDatabase(name string, cache, handles int, freezer, di var statediskdb ethdb.Database var err error // Open the separated state database if the state directory exists - if n.HasSeparateTrieDir() { + if n.IsSeparatedDB() { // Allocate half of the handles and cache to this separate state data database - statediskdb, err = n.OpenDatabaseWithFreezer(name+"/state", 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) if err != nil { return nil, err } @@ -799,7 +799,7 @@ func (n *Node) OpenAndMergeDatabase(name string, cache, handles int, freezer, di chainDataHandles = int(float64(chainDataHandles) * 0.6) } - chainDB, err := n.OpenDatabaseWithFreezer(name, cache, chainDataHandles, freezer, namespace, readonly, false, false, pruneAncientData, false) + chainDB, err := n.OpenDatabaseWithFreezer(name, cache, chainDataHandles, freezer, namespace, readonly, false, false, pruneAncientData) if err != nil { return nil, err } @@ -824,7 +824,7 @@ func (n *Node) OpenAndMergeDatabase(name string, cache, handles int, freezer, di // also attaching a chain freezer to it that moves ancient chain data from the // database to immutable append-only files. If the node is an ephemeral one, a // memory database is returned. -func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient, namespace string, readonly, disableFreeze, isLastOffset, pruneAncientData, isSeparateStateDB bool) (ethdb.Database, error) { +func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient, namespace string, readonly, disableFreeze, isLastOffset, pruneAncientData bool) (ethdb.Database, error) { n.lock.Lock() defer n.lock.Unlock() if n.state == closedState { @@ -833,9 +833,6 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient, var db ethdb.Database var err error if n.config.DataDir == "" { - if isSeparateStateDB { - return nil, ErrSeprateDBDatadir - } db = rawdb.NewMemoryDatabase() } else { db, err = rawdb.Open(rawdb.OpenOptions{ @@ -858,8 +855,8 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient, return db, err } -// HasSeparateTrieDir check the state subdirectory of db, if subdirectory exists, return true -func (n *Node) HasSeparateTrieDir() bool { +// IsSeparatedDB check the state subdirectory of db, if subdirectory exists, return true +func (n *Node) IsSeparatedDB() bool { separateDir := filepath.Join(n.ResolvePath("chaindata"), "state") fileInfo, err := os.Stat(separateDir) if os.IsNotExist(err) { From 474fcb47537b449ab06fe8f67b6b765630a67366 Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Wed, 6 Mar 2024 21:04:38 +0800 Subject: [PATCH 17/18] fix: fix inspect & dump commnd --- cmd/geth/chaincmd.go | 3 +-- cmd/geth/dbcmd.go | 2 +- core/rawdb/ancient_utils.go | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 459a68bfc2..493e80e30c 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -609,7 +609,6 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth } db := utils.MakeChainDatabase(ctx, stack, true, false) - defer db.Close() scheme, err := rawdb.ParseStateScheme(ctx.String(utils.StateSchemeFlag.Name), db) if err != nil { return nil, nil, common.Hash{}, err @@ -618,7 +617,7 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth fmt.Println("You are using geth dump in path mode, please use `geth dump-roothash` command to get all available blocks.") } - var header *types.Header + header := &types.Header{} if ctx.NArg() == 1 { arg := ctx.Args().First() if hashish(arg) { diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index f552b1d660..b1479c5c3e 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -601,7 +601,7 @@ func dbCompact(ctx *cli.Context) error { log.Info("Stats after compaction") showLeveldbStats(db) if statediskdb != nil { - fmt.Println("show stats of state store") + fmt.Println("show stats of state store after compaction") showLeveldbStats(statediskdb) } return nil diff --git a/core/rawdb/ancient_utils.go b/core/rawdb/ancient_utils.go index f7a0208d38..1d780063ff 100644 --- a/core/rawdb/ancient_utils.go +++ b/core/rawdb/ancient_utils.go @@ -91,8 +91,7 @@ func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) { infos = append(infos, info) case StateFreezerName: - if - ReadStateScheme(db) != PathScheme { + if ReadStateScheme(db) != PathScheme || db.StateStore() != nil { continue } datadir, err := db.AncientDatadir() From 32159eb2e985c038b883fcab5f73801cfce241ed Mon Sep 17 00:00:00 2001 From: flywukong <2229306838@qq.com> Date: Fri, 8 Mar 2024 14:57:16 +0800 Subject: [PATCH 18/18] fix: delete blank lines --- eth/backend.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/eth/backend.go b/eth/backend.go index c7790b4a9f..9d9197811b 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -142,7 +142,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if err != nil { return nil, err } - config.StateScheme, err = rawdb.ParseStateScheme(config.StateScheme, chainDb) if err != nil { return nil, err @@ -279,7 +278,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { peers := newPeerSet() bcOps = append(bcOps, core.EnableBlockValidator(chainConfig, eth.engine, config.TriesVerifyMode, peers)) - eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, eth.shouldPreserve, &config.TransactionHistory, bcOps...) if err != nil { return nil, err