@@ -374,6 +374,75 @@ func ExportPreimages(db ethdb.Database, fn string) error {
374374 return nil
375375}
376376
377+ // ExportSnapshotPreimages exports the preimages corresponding to the enumeration of
378+ // the snapshot for a given root.
379+ func ExportSnapshotPreimages (chain * core.BlockChain , fn string , root common.Hash ) error {
380+ log .Info ("Exporting preimages" , "file" , fn )
381+
382+ fh , err := os .OpenFile (fn , os .O_CREATE | os .O_WRONLY | os .O_TRUNC , os .ModePerm )
383+ if err != nil {
384+ return err
385+ }
386+ defer fh .Close ()
387+
388+ writer := bufio .NewWriter (fh )
389+ defer writer .Flush ()
390+
391+ statedb , err := chain .State ()
392+ if err != nil {
393+ return fmt .Errorf ("failed to open statedb: %w" , err )
394+ }
395+
396+ if root == (common.Hash {}) {
397+ root = chain .CurrentBlock ().Root
398+ }
399+
400+ accIt , err := chain .Snapshots ().AccountIterator (root , common.Hash {})
401+ if err != nil {
402+ return err
403+ }
404+ defer accIt .Release ()
405+
406+ count := 0
407+ for accIt .Next () {
408+ acc , err := types .FullAccount (accIt .Account ())
409+ if err != nil {
410+ return fmt .Errorf ("invalid account encountered during traversal: %s" , err )
411+ }
412+ addr := rawdb .ReadPreimage (statedb .Database ().DiskDB (), accIt .Hash ())
413+ if len (addr ) != 20 {
414+ return fmt .Errorf ("addr len is zero is not 32: %d" , len (addr ))
415+ }
416+ if _ , err := writer .Write (addr ); err != nil {
417+ return fmt .Errorf ("failed to write addr preimage: %w" , err )
418+ }
419+
420+ if acc .Root != (common.Hash {}) && acc .Root != types .EmptyRootHash {
421+ stIt , err := chain .Snapshots ().StorageIterator (root , accIt .Hash (), common.Hash {})
422+ if err != nil {
423+ return fmt .Errorf ("failed to create storage iterator: %w" , err )
424+ }
425+ for stIt .Next () {
426+ slotnr := rawdb .ReadPreimage (statedb .Database ().DiskDB (), stIt .Hash ())
427+ if len (slotnr ) != 32 {
428+ return fmt .Errorf ("slotnr not 32 len" )
429+ }
430+ if _ , err := writer .Write (slotnr ); err != nil {
431+ return fmt .Errorf ("failed to write slotnr preimage: %w" , err )
432+ }
433+ }
434+ stIt .Release ()
435+ }
436+ count ++
437+ if count % 100000 == 0 {
438+ log .Info ("Last exported account" , "account" , accIt .Hash ())
439+ }
440+ }
441+
442+ log .Info ("Exported preimages" , "file" , fn )
443+ return nil
444+ }
445+
377446// exportHeader is used in the export/import flow. When we do an export,
378447// the first element we output is the exportHeader.
379448// Whenever a backwards-incompatible change is made, the Version header
0 commit comments