-
Notifications
You must be signed in to change notification settings - Fork 20.2k
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
cmd: command to dump preimages enumerated in snapshot order, in a flat file #27819
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -374,6 +374,73 @@ func ExportPreimages(db ethdb.Database, fn string) error { | |
return nil | ||
} | ||
|
||
// ExportOverlayPreimages exports all known hash preimages into the specified file, | ||
// in the same order as expected by the overlay tree migration. | ||
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. Please specify what that "same order" entails |
||
func ExportOverlayPreimages(chain *core.BlockChain, fn string) error { | ||
log.Info("Exporting preimages", "file", fn) | ||
|
||
fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) | ||
if err != nil { | ||
return err | ||
} | ||
Comment on lines
+382
to
+385
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. truncate? Wouldn't it be nicer if we could abort/resume, somehow? |
||
defer fh.Close() | ||
|
||
writer := bufio.NewWriter(fh) | ||
defer writer.Flush() | ||
|
||
statedb, err := chain.State() | ||
if err != nil { | ||
return fmt.Errorf("failed to open statedb: %w", err) | ||
} | ||
|
||
mptRoot := chain.CurrentBlock().Root | ||
|
||
accIt, err := chain.Snapshots().AccountIterator(mptRoot, common.Hash{}) | ||
if err != nil { | ||
return err | ||
} | ||
defer accIt.Release() | ||
|
||
count := 0 | ||
for accIt.Next() { | ||
acc, err := types.FullAccount(accIt.Account()) | ||
if err != nil { | ||
return fmt.Errorf("invalid account encountered during traversal: %s", err) | ||
} | ||
addr := rawdb.ReadPreimage(statedb.Database().DiskDB(), accIt.Hash()) | ||
Comment on lines
+405
to
+410
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. Hm, interesting. So, your way of doing this is to
An alternative way to do it would be to iterate the premages: in a first phase, out to an external file. In a second phase, that file could be (iteratively) sorted by post-image instead of pre-image. It would be interesting to see the differences in speed between the two approaches. A benefit with the second approach is that it wouldn't be sensitive to new data -- if you get an additional chunk of preimages (either from a few more blocks, or some external source), you could just append them to the "unsorted" file, and then re-sort it. 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. Ah, I see now that the order you want is not just "ordered by post-hash", the ordering is "ordered by post-hash account, then the preimages for that account's storage trie preimages". So the final ordering would be
Seems like a pretty strange ordering -- and also highly sensitive to changes in state. If you advance one block, you need to redo everything, because the ordering is state-dependent and cannot be performed given only the data itself. |
||
if len(addr) != 20 { | ||
return fmt.Errorf("addr len is zero is not 32: %d", len(addr)) | ||
} | ||
if _, err := writer.Write(addr); err != nil { | ||
return fmt.Errorf("failed to write addr preimage: %w", err) | ||
} | ||
|
||
if acc.Root == types.EmptyRootHash { | ||
stIt, err := chain.Snapshots().StorageIterator(mptRoot, accIt.Hash(), common.Hash{}) | ||
Comment on lines
+418
to
+419
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. This seems bass-ackwards. No need to create an iterator if the root is the empty root hash. Tho it's faster for sure :) |
||
if err != nil { | ||
return fmt.Errorf("failed to create storage iterator: %w", err) | ||
} | ||
for stIt.Next() { | ||
slotnr := rawdb.ReadPreimage(statedb.Database().DiskDB(), stIt.Hash()) | ||
if len(slotnr) != 32 { | ||
return fmt.Errorf("slotnr not 32 len") | ||
} | ||
if _, err := writer.Write(slotnr); err != nil { | ||
return fmt.Errorf("failed to write slotnr preimage: %w", err) | ||
} | ||
} | ||
stIt.Release() | ||
} | ||
count++ | ||
if count%100000 == 0 { | ||
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. Please instead add a log output every |
||
log.Info("Last exported account", "account", accIt.Hash()) | ||
} | ||
} | ||
|
||
log.Info("Exported preimages", "file", fn) | ||
return nil | ||
} | ||
|
||
// exportHeader is used in the export/import flow. When we do an export, | ||
// the first element we output is the exportHeader. | ||
// Whenever a backwards-incompatible change is made, the Version header | ||
|
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.
I mean, it's just exporting preimages, right?