-
Notifications
You must be signed in to change notification settings - Fork 20.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
core/state/snapshot: clean up dangling storages in snapshot generation #24665
Closed
Closed
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
be4415a
core/state/snapshot: check dangling storages when generating snapshot
rjl493456442 fbc4a21
core/state/snapshot: polish
rjl493456442 49f4cb5
core/state/snapshot: wipe the last part of the dangling storages
rjl493456442 18c52ce
core/state/snapshot: fix and add tests
rjl493456442 95c5df0
core/state/snapshot: fix comment
rjl493456442 0ab13fa
core, cmd: expose dangling storage detector for wider usage
rjl493456442 a5f8b36
cmd/geth: use detector in cmd
rjl493456442 592d42f
core/state/snapshot: rename variable
rjl493456442 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
// Copyright 2022 The go-ethereum Authors | ||
// This file is part of the go-ethereum library. | ||
// | ||
// The go-ethereum library is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU Lesser General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// The go-ethereum library is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU Lesser General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU Lesser General Public License | ||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
package snapshot | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"time" | ||
|
||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/common/hexutil" | ||
"github.com/ethereum/go-ethereum/core/rawdb" | ||
"github.com/ethereum/go-ethereum/ethdb" | ||
"github.com/ethereum/go-ethereum/log" | ||
) | ||
|
||
// DanglingRange describes the range for detecting dangling storages. | ||
type DanglingRange struct { | ||
db ethdb.KeyValueStore // The database stores the snapshot data | ||
start []byte // The start of the key range | ||
limit []byte // The last of the key range | ||
|
||
result []common.Hash // The list of account hashes which have the dangling storages | ||
duration time.Duration // Total time spent on the iteration | ||
} | ||
|
||
// NewDanglingRange initializes a dangling storage scanner and detects all the | ||
// dangling accounts out. | ||
func NewDanglingRange(db ethdb.KeyValueStore, start, limit []byte, report bool) *DanglingRange { | ||
r := &DanglingRange{ | ||
db: db, | ||
start: start, | ||
limit: limit, | ||
} | ||
r.result, r.duration = r.detect(report) | ||
|
||
// Update metrics | ||
snapDanglingStoragesCounter.Inc(int64(len(r.result))) | ||
snapDanglingStoragesTimer.Update(r.duration) | ||
|
||
if len(r.result) > 0 { | ||
log.Warn("Detected dangling storages", "number", len(r.result), "start", hexutil.Encode(start), "limit", hexutil.Encode(limit), "elapsed", common.PrettyDuration(r.duration)) | ||
} else { | ||
logger := log.Debug | ||
if report { | ||
logger = log.Info | ||
} | ||
logger("Verified snapshot storages", "start", hexutil.Encode(start), "limit", hexutil.Encode(limit), "elapsed", common.PrettyDuration(r.duration)) | ||
} | ||
return r | ||
} | ||
|
||
// detect iterates the storage snapshot in the specified key range and | ||
// returns a list of account hash of the dangling storages. Note both | ||
// start and limit are included for iteration. | ||
func (r *DanglingRange) detect(report bool) ([]common.Hash, time.Duration) { | ||
var ( | ||
checked []byte | ||
result []common.Hash | ||
start = time.Now() | ||
lastReport = time.Now() | ||
) | ||
iter := rawdb.NewKeyLengthIterator(r.db.NewIterator(rawdb.SnapshotStoragePrefix, r.start), len(rawdb.SnapshotStoragePrefix)+2*common.HashLength) | ||
defer iter.Release() | ||
|
||
for iter.Next() { | ||
account := iter.Key()[len(rawdb.SnapshotStoragePrefix) : len(rawdb.SnapshotStoragePrefix)+common.HashLength] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know that the way you have written it is "more correct", but IMO it's easier to read on the form
Might be a minority opinion though ... |
||
if r.limit != nil && bytes.Compare(account, r.limit) > 0 { | ||
break | ||
} | ||
// Skip unnecessary checks for checked storage. | ||
if bytes.Equal(account, checked) { | ||
continue | ||
} | ||
checked = common.CopyBytes(account) | ||
|
||
// Check the presence of the corresponding account. | ||
accountHash := common.BytesToHash(account) | ||
data := rawdb.ReadAccountSnapshot(r.db, accountHash) | ||
if len(data) != 0 { | ||
continue | ||
} | ||
result = append(result, accountHash) | ||
|
||
if report { | ||
log.Warn("Dangling storage - missing account", "account", fmt.Sprintf("%#x", accountHash)) | ||
} | ||
if time.Since(lastReport) > time.Second*8 && report { | ||
log.Info("Detecting dangling storage", "at", fmt.Sprintf("%#x", accountHash), "elapsed", common.PrettyDuration(time.Since(start))) | ||
lastReport = time.Now() | ||
} | ||
} | ||
return result, time.Since(start) | ||
} | ||
|
||
// cleanup wipes the dangling storages which fall within the range before the given key. | ||
func (r *DanglingRange) cleanup(limit []byte) error { | ||
var ( | ||
err error | ||
wiped int | ||
) | ||
for _, accountHash := range r.result { | ||
if limit != nil && bytes.Compare(accountHash.Bytes(), limit) >= 0 { | ||
break | ||
} | ||
prefix := append(rawdb.SnapshotStoragePrefix, accountHash.Bytes()...) | ||
keylen := len(rawdb.SnapshotStoragePrefix) + 2*common.HashLength | ||
if err = wipeKeyRange(r.db, "storage", prefix, nil, nil, keylen, snapWipedStorageMeter, false); err != nil { | ||
break | ||
} | ||
wiped += 1 | ||
} | ||
r.result = r.result[wiped:] | ||
return err | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps?