Skip to content

Commit 59f7b28

Browse files
authored
cmd, core, eth, graphql, trie: no persisted clean trie cache file (#27525)
The clean trie cache is persisted periodically, therefore Geth can quickly warmup the cache in next restart. However it will reduce the robustness of system. The assumption is held in Geth that if the parent trie node is present, then the entire sub-trie associated with the parent are all prensent. Imagine the scenario that Geth rewinds itself to a past block and restart, but Geth finds the root node of "future state" in clean cache then regard this state is present in disk, while is not in fact. Another example is offline pruning tool. Whenever an offline pruning is performed, the clean cache file has to be removed to aviod hitting the root node of "deleted states" in clean cache. All in all, compare with the minor performance gain, system robustness is something we care more.
1 parent 6ca3ef9 commit 59f7b28

File tree

13 files changed

+59
-186
lines changed

13 files changed

+59
-186
lines changed

cmd/devp2p/internal/ethtest/suite_test.go

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,13 @@ func setupGeth(stack *node.Node) error {
109109
}
110110

111111
backend, err := eth.New(stack, &ethconfig.Config{
112-
Genesis: &chain.genesis,
113-
NetworkId: chain.genesis.Config.ChainID.Uint64(), // 19763
114-
DatabaseCache: 10,
115-
TrieCleanCache: 10,
116-
TrieCleanCacheJournal: "",
117-
TrieCleanCacheRejournal: 60 * time.Minute,
118-
TrieDirtyCache: 16,
119-
TrieTimeout: 60 * time.Minute,
120-
SnapshotCache: 10,
112+
Genesis: &chain.genesis,
113+
NetworkId: chain.genesis.Config.ChainID.Uint64(), // 19763
114+
DatabaseCache: 10,
115+
TrieCleanCache: 10,
116+
TrieDirtyCache: 16,
117+
TrieTimeout: 60 * time.Minute,
118+
SnapshotCache: 10,
121119
})
122120
if err != nil {
123121
return err

cmd/geth/config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,10 @@ func deprecated(field string) bool {
276276
return true
277277
case "ethconfig.Config.EWASMInterpreter":
278278
return true
279+
case "ethconfig.Config.TrieCleanCacheJournal":
280+
return true
281+
case "ethconfig.Config.TrieCleanCacheRejournal":
282+
return true
279283
default:
280284
return false
281285
}

cmd/geth/snapshot.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ var (
5050
ArgsUsage: "<root>",
5151
Action: pruneState,
5252
Flags: flags.Merge([]cli.Flag{
53-
utils.CacheTrieJournalFlag,
5453
utils.BloomFilterSizeFlag,
5554
}, utils.NetworkFlags, utils.DatabasePathFlags),
5655
Description: `
@@ -160,15 +159,14 @@ block is used.
160159
// Deprecation: this command should be deprecated once the hash-based
161160
// scheme is deprecated.
162161
func pruneState(ctx *cli.Context) error {
163-
stack, config := makeConfigNode(ctx)
162+
stack, _ := makeConfigNode(ctx)
164163
defer stack.Close()
165164

166165
chaindb := utils.MakeChainDatabase(ctx, stack, false)
167166
defer chaindb.Close()
168167

169168
prunerconfig := pruner.Config{
170169
Datadir: stack.ResolvePath(""),
171-
Cachedir: stack.ResolvePath(config.Eth.TrieCleanCacheJournal),
172170
BloomSize: ctx.Uint64(utils.BloomFilterSizeFlag.Name),
173171
}
174172
pruner, err := pruner.NewPruner(chaindb, prunerconfig)

cmd/utils/flags.go

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -410,18 +410,6 @@ var (
410410
Value: 15,
411411
Category: flags.PerfCategory,
412412
}
413-
CacheTrieJournalFlag = &cli.StringFlag{
414-
Name: "cache.trie.journal",
415-
Usage: "Disk journal directory for trie cache to survive node restarts",
416-
Value: ethconfig.Defaults.TrieCleanCacheJournal,
417-
Category: flags.PerfCategory,
418-
}
419-
CacheTrieRejournalFlag = &cli.DurationFlag{
420-
Name: "cache.trie.rejournal",
421-
Usage: "Time interval to regenerate the trie cache journal",
422-
Value: ethconfig.Defaults.TrieCleanCacheRejournal,
423-
Category: flags.PerfCategory,
424-
}
425413
CacheGCFlag = &cli.IntFlag{
426414
Name: "cache.gc",
427415
Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)",
@@ -1710,12 +1698,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
17101698
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) {
17111699
cfg.TrieCleanCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100
17121700
}
1713-
if ctx.IsSet(CacheTrieJournalFlag.Name) {
1714-
cfg.TrieCleanCacheJournal = ctx.String(CacheTrieJournalFlag.Name)
1715-
}
1716-
if ctx.IsSet(CacheTrieRejournalFlag.Name) {
1717-
cfg.TrieCleanCacheRejournal = ctx.Duration(CacheTrieRejournalFlag.Name)
1718-
}
17191701
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) {
17201702
cfg.TrieDirtyCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100
17211703
}

cmd/utils/flags_legacy.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ var ShowDeprecated = &cli.Command{
3333

3434
var DeprecatedFlags = []cli.Flag{
3535
NoUSBFlag,
36+
CacheTrieJournalFlag,
37+
CacheTrieRejournalFlag,
3638
}
3739

3840
var (
@@ -42,6 +44,17 @@ var (
4244
Usage: "Disables monitoring for and managing USB hardware wallets (deprecated)",
4345
Category: flags.DeprecatedCategory,
4446
}
47+
// (Deprecated June 2023, shown in aliased flags section)
48+
CacheTrieJournalFlag = &cli.StringFlag{
49+
Name: "cache.trie.journal",
50+
Usage: "Disk journal directory for trie cache to survive node restarts",
51+
Category: flags.PerfCategory,
52+
}
53+
CacheTrieRejournalFlag = &cli.DurationFlag{
54+
Name: "cache.trie.rejournal",
55+
Usage: "Time interval to regenerate the trie cache journal",
56+
Category: flags.PerfCategory,
57+
}
4558
)
4659

4760
// showDeprecated displays deprecated flags that will be soon removed from the codebase.

core/blockchain.go

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,6 @@ const (
130130
// that's resident in a blockchain.
131131
type CacheConfig struct {
132132
TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory
133-
TrieCleanJournal string // Disk journal for saving clean cache entries.
134-
TrieCleanRejournal time.Duration // Time interval to dump clean cache to disk periodically
135133
TrieCleanNoPrefetch bool // Whether to disable heuristic state prefetching for followup blocks
136134
TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk
137135
TrieDirtyDisabled bool // Whether to disable trie write caching and GC altogether (archive node)
@@ -238,7 +236,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
238236
// Open trie database with provided config
239237
triedb := trie.NewDatabaseWithConfig(db, &trie.Config{
240238
Cache: cacheConfig.TrieCleanLimit,
241-
Journal: cacheConfig.TrieCleanJournal,
242239
Preimages: cacheConfig.Preimages,
243240
})
244241
// Setup the genesis block, commit the provided genesis specification
@@ -411,18 +408,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
411408
bc.wg.Add(1)
412409
go bc.updateFutureBlocks()
413410

414-
// If periodic cache journal is required, spin it up.
415-
if bc.cacheConfig.TrieCleanRejournal > 0 {
416-
if bc.cacheConfig.TrieCleanRejournal < time.Minute {
417-
log.Warn("Sanitizing invalid trie cache journal time", "provided", bc.cacheConfig.TrieCleanRejournal, "updated", time.Minute)
418-
bc.cacheConfig.TrieCleanRejournal = time.Minute
419-
}
420-
bc.wg.Add(1)
421-
go func() {
422-
defer bc.wg.Done()
423-
bc.triedb.SaveCachePeriodically(bc.cacheConfig.TrieCleanJournal, bc.cacheConfig.TrieCleanRejournal, bc.quit)
424-
}()
425-
}
426411
// Rewind the chain in case of an incompatible config upgrade.
427412
if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
428413
log.Warn("Rewinding chain to upgrade configuration", "err", compat)
@@ -987,11 +972,6 @@ func (bc *BlockChain) Stop() {
987972
if err := bc.stateCache.TrieDB().Close(); err != nil {
988973
log.Error("Failed to close trie db", "err", err)
989974
}
990-
// Ensure all live cached entries be saved into disk, so that we can skip
991-
// cache warmup when node restarts.
992-
if bc.cacheConfig.TrieCleanJournal != "" {
993-
bc.triedb.SaveCache(bc.cacheConfig.TrieCleanJournal)
994-
}
995975
log.Info("Blockchain stopped")
996976
}
997977

core/state/pruner/pruner.go

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ const (
5757
// Config includes all the configurations for pruning.
5858
type Config struct {
5959
Datadir string // The directory of the state database
60-
Cachedir string // The directory of state clean cache
6160
BloomSize uint64 // The Megabytes of memory allocated to bloom-filter
6261
}
6362

@@ -241,7 +240,7 @@ func (p *Pruner) Prune(root common.Hash) error {
241240
return err
242241
}
243242
if stateBloomRoot != (common.Hash{}) {
244-
return RecoverPruning(p.config.Datadir, p.db, p.config.Cachedir)
243+
return RecoverPruning(p.config.Datadir, p.db)
245244
}
246245
// If the target state root is not specified, use the HEAD-127 as the
247246
// target. The reason for picking it is:
@@ -299,12 +298,6 @@ func (p *Pruner) Prune(root common.Hash) error {
299298
log.Info("Selecting user-specified state as the pruning target", "root", root)
300299
}
301300
}
302-
// Before start the pruning, delete the clean trie cache first.
303-
// It's necessary otherwise in the next restart we will hit the
304-
// deleted state root in the "clean cache" so that the incomplete
305-
// state is picked for usage.
306-
deleteCleanTrieCache(p.config.Cachedir)
307-
308301
// All the state roots of the middle layer should be forcibly pruned,
309302
// otherwise the dangling state will be left.
310303
middleRoots := make(map[common.Hash]struct{})
@@ -342,7 +335,7 @@ func (p *Pruner) Prune(root common.Hash) error {
342335
// pruning can be resumed. What's more if the bloom filter is constructed, the
343336
// pruning **has to be resumed**. Otherwise a lot of dangling nodes may be left
344337
// in the disk.
345-
func RecoverPruning(datadir string, db ethdb.Database, trieCachePath string) error {
338+
func RecoverPruning(datadir string, db ethdb.Database) error {
346339
stateBloomPath, stateBloomRoot, err := findBloomFilter(datadir)
347340
if err != nil {
348341
return err
@@ -378,12 +371,6 @@ func RecoverPruning(datadir string, db ethdb.Database, trieCachePath string) err
378371
}
379372
log.Info("Loaded state bloom filter", "path", stateBloomPath)
380373

381-
// Before start the pruning, delete the clean trie cache first.
382-
// It's necessary otherwise in the next restart we will hit the
383-
// deleted state root in the "clean cache" so that the incomplete
384-
// state is picked for usage.
385-
deleteCleanTrieCache(trieCachePath)
386-
387374
// All the state roots of the middle layers should be forcibly pruned,
388375
// otherwise the dangling state will be left.
389376
var (
@@ -497,23 +484,3 @@ func findBloomFilter(datadir string) (string, common.Hash, error) {
497484
}
498485
return stateBloomPath, stateBloomRoot, nil
499486
}
500-
501-
const warningLog = `
502-
503-
WARNING!
504-
505-
The clean trie cache is not found. Please delete it by yourself after the
506-
pruning. Remember don't start the Geth without deleting the clean trie cache
507-
otherwise the entire database may be damaged!
508-
509-
Check the command description "geth snapshot prune-state --help" for more details.
510-
`
511-
512-
func deleteCleanTrieCache(path string) {
513-
if !common.FileExist(path) {
514-
log.Warn(warningLog)
515-
return
516-
}
517-
os.RemoveAll(path)
518-
log.Info("Deleted trie clean cache", "path", path)
519-
}

eth/backend.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
132132
if err != nil {
133133
return nil, err
134134
}
135-
if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb, stack.ResolvePath(config.TrieCleanCacheJournal)); err != nil {
135+
if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb); err != nil {
136136
log.Error("Failed to recover state", "error", err)
137137
}
138138
// Transfer mining-related config to the ethash config.
@@ -184,8 +184,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
184184
}
185185
cacheConfig = &core.CacheConfig{
186186
TrieCleanLimit: config.TrieCleanCache,
187-
TrieCleanJournal: stack.ResolvePath(config.TrieCleanCacheJournal),
188-
TrieCleanRejournal: config.TrieCleanCacheRejournal,
189187
TrieCleanNoPrefetch: config.NoPrefetch,
190188
TrieDirtyLimit: config.TrieDirtyCache,
191189
TrieDirtyDisabled: config.NoPruning,

eth/ethconfig/config.go

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -57,25 +57,23 @@ var LightClientGPO = gasprice.Config{
5757

5858
// Defaults contains default settings for use on the Ethereum main net.
5959
var Defaults = Config{
60-
SyncMode: downloader.SnapSync,
61-
NetworkId: 1,
62-
TxLookupLimit: 2350000,
63-
LightPeers: 100,
64-
UltraLightFraction: 75,
65-
DatabaseCache: 512,
66-
TrieCleanCache: 154,
67-
TrieCleanCacheJournal: "triecache",
68-
TrieCleanCacheRejournal: 60 * time.Minute,
69-
TrieDirtyCache: 256,
70-
TrieTimeout: 60 * time.Minute,
71-
SnapshotCache: 102,
72-
FilterLogCacheSize: 32,
73-
Miner: miner.DefaultConfig,
74-
TxPool: legacypool.DefaultConfig,
75-
RPCGasCap: 50000000,
76-
RPCEVMTimeout: 5 * time.Second,
77-
GPO: FullNodeGPO,
78-
RPCTxFeeCap: 1, // 1 ether
60+
SyncMode: downloader.SnapSync,
61+
NetworkId: 1,
62+
TxLookupLimit: 2350000,
63+
LightPeers: 100,
64+
UltraLightFraction: 75,
65+
DatabaseCache: 512,
66+
TrieCleanCache: 154,
67+
TrieDirtyCache: 256,
68+
TrieTimeout: 60 * time.Minute,
69+
SnapshotCache: 102,
70+
FilterLogCacheSize: 32,
71+
Miner: miner.DefaultConfig,
72+
TxPool: legacypool.DefaultConfig,
73+
RPCGasCap: 50000000,
74+
RPCEVMTimeout: 5 * time.Second,
75+
GPO: FullNodeGPO,
76+
RPCTxFeeCap: 1, // 1 ether
7977
}
8078

8179
//go:generate go run github.com/fjl/gencodec -type Config -formats toml -out gen_config.go
@@ -124,13 +122,11 @@ type Config struct {
124122
DatabaseCache int
125123
DatabaseFreezer string
126124

127-
TrieCleanCache int
128-
TrieCleanCacheJournal string `toml:",omitempty"` // Disk journal directory for trie cache to survive node restarts
129-
TrieCleanCacheRejournal time.Duration `toml:",omitempty"` // Time interval to regenerate the journal for clean cache
130-
TrieDirtyCache int
131-
TrieTimeout time.Duration
132-
SnapshotCache int
133-
Preimages bool
125+
TrieCleanCache int
126+
TrieDirtyCache int
127+
TrieTimeout time.Duration
128+
SnapshotCache int
129+
Preimages bool
134130

135131
// This is the number of blocks for which logs will be cached in the filter system.
136132
FilterLogCacheSize int

eth/ethconfig/gen_config.go

Lines changed: 0 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)