From 5a254c48e33d9d4996af642e24b66db75c2c531e Mon Sep 17 00:00:00 2001 From: j75689 Date: Wed, 27 Apr 2022 10:20:27 +0800 Subject: [PATCH] add interval when getting ErrSnapshotStale --- core/state/state_object.go | 8 ++++++++ core/state/statedb.go | 13 ++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/core/state/state_object.go b/core/state/state_object.go index b454de272d..0263d8d64b 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -278,6 +278,14 @@ func (s *StateObject) GetCommittedState(db Database, key common.Hash) common.Has } // ErrSnapshotStale may occur due to diff layers in the update, so we should try again in noTrie mode. if s.db.NoTrie() && err != nil && errors.Is(err, snapshot.ErrSnapshotStale) { + // This error occurs when statedb.snaps.Cap changes the state of the merged difflayer + // to stale during the refresh of the difflayer, indicating that it is about to be discarded. + // Since the difflayer is refreshed in parallel, + // there is a small chance that the difflayer of the stale will be read while reading, + // resulting in an empty array being returned here. + // Therefore, noTrie mode must retry here, + // and add a time interval when retrying to avoid stacking too much and causing OOM. + time.Sleep(snapshotStaleRetryInterval) return s.GetCommittedState(db, key) } // If snapshot unavailable or reading from it failed, load from the database diff --git a/core/state/statedb.go b/core/state/statedb.go index 7ceb8e0e47..c294c73667 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -39,7 +39,10 @@ import ( "github.com/ethereum/go-ethereum/trie" ) -const defaultNumOfSlots = 100 +const ( + defaultNumOfSlots = 100 + snapshotStaleRetryInterval = time.Millisecond * 100 +) type revision struct { id int @@ -677,6 +680,14 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *StateObject { // ErrSnapshotStale may occur due to diff layers in the update, so we should try again in noTrie mode. if s.NoTrie() && err != nil && errors.Is(err, snapshot.ErrSnapshotStale) { + // This error occurs when statedb.snaps.Cap changes the state of the merged difflayer + // to stale during the refresh of the difflayer, indicating that it is about to be discarded. + // Since the difflayer is refreshed in parallel, + // there is a small chance that the difflayer of the stale will be read while reading, + // resulting in an empty array being returned here. + // Therefore, noTrie mode must retry here, + // and add a time interval when retrying to avoid stacking too much and causing OOM. + time.Sleep(snapshotStaleRetryInterval) return s.getDeletedStateObject(addr) }