From 6b6fd126dc424cd704c11e9e99245a51cd626990 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 16 Nov 2023 17:02:48 +0000 Subject: [PATCH 1/2] don't close triedb too early in eth.StateAtBlock --- eth/state_accessor.go | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/eth/state_accessor.go b/eth/state_accessor.go index 9c80630d5a..99dd4d1a58 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -77,6 +77,7 @@ func (eth *Ethereum) StateAtBlock(ctx context.Context, block *types.Block, reexe }, nil } } + closeTrieDBInDefer := true // The state is both for reading and writing, or it's unavailable in disk, // try to construct/recover the state over an ephemeral trie.Database for // isolating the live one. @@ -85,10 +86,15 @@ func (eth *Ethereum) StateAtBlock(ctx context.Context, block *types.Block, reexe // Create an ephemeral trie.Database for isolating the live one. Otherwise // the internal junks created by tracing will be persisted into the disk. database = state.NewDatabaseWithConfig(eth.chainDb, &trie.Config{Cache: 16}) - defer database.TrieDB().Close() + defer func() { + if closeTrieDBInDefer { + database.TrieDB().Close() + } + }() if statedb, err = state.New(block.Root(), database, nil); err == nil { log.Info("Found disk backend for state trie", "root", block.Root(), "number", block.Number()) - return statedb, noopReleaser, nil + closeTrieDBInDefer = false + return statedb, func() { database.TrieDB().Close() }, nil } } // The optional base statedb is given, mark the start point as parent block @@ -101,7 +107,11 @@ func (eth *Ethereum) StateAtBlock(ctx context.Context, block *types.Block, reexe // Create an ephemeral trie.Database for isolating the live one. Otherwise // the internal junks created by tracing will be persisted into the disk. database = state.NewDatabaseWithConfig(eth.chainDb, &trie.Config{Cache: 16}) - defer database.TrieDB().Close() + defer func() { + if closeTrieDBInDefer { + database.TrieDB().Close() + } + }() // If we didn't check the live database, do check state over ephemeral database, // otherwise we would rewind past a persisted block (specific corner case is @@ -109,7 +119,8 @@ func (eth *Ethereum) StateAtBlock(ctx context.Context, block *types.Block, reexe if !readOnly { statedb, err = state.New(current.Root(), database, nil) if err == nil { - return statedb, noopReleaser, nil + closeTrieDBInDefer = false + return statedb, func() { database.TrieDB().Close() }, nil } } // Database does not have the state for the given block, try to regenerate @@ -187,7 +198,11 @@ func (eth *Ethereum) StateAtBlock(ctx context.Context, block *types.Block, reexe nodes, imgs := database.TrieDB().Size() log.Info("Historical state regenerated", "block", current.NumberU64(), "elapsed", time.Since(start), "nodes", nodes, "preimages", imgs) } - return statedb, func() { database.TrieDB().Dereference(block.Root()) }, nil + closeTrieDBInDefer = false + return statedb, func() { + database.TrieDB().Dereference(block.Root()) + database.TrieDB().Close() + }, nil } // stateAtTransaction returns the execution environment of a certain transaction. From f6552ab44f39a5370768f8efd8c9d547a7c95a68 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 16 Nov 2023 18:02:34 +0000 Subject: [PATCH 2/2] remove unused noopReleaser --- eth/state_accessor.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/eth/state_accessor.go b/eth/state_accessor.go index 99dd4d1a58..ff18d27054 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -32,10 +32,6 @@ import ( "github.com/ethereum/go-ethereum/trie" ) -// noopReleaser is returned in case there is no operation expected -// for releasing state. -var noopReleaser = tracers.StateReleaseFunc(func() {}) - // StateAtBlock retrieves the state database associated with a certain block. // If no state is locally available for the given block, a number of blocks // are attempted to be reexecuted to generate the desired state. The optional